【揭秘】C语言类型转换时发生了什么?
ID:技术让梦想更伟大
作者:李肖遥
在C语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统,我们常用的算术类型包括两种类型:整数类型和浮点类型。那么相互之间具体是怎么转化的呢?
了解一下类型转换
不同数据类型的存储大小和值范围是不一样的,程序在初始化的时候就已经设定了,例如:
int a = 9;
float b = 8.5;
a,b占的字节大小不一样,这个我们应该都知道,在C语言中一个表达式允许不同类型的数据进行运算,例如:
int a = 9;
float b = 8.5,c;
c = a + b;
因为计算机硬件在进行算术操作时,要求各操作数的类型具有相同的存储位数以及一样的存储方式,所以就出现了类型转换。
对于某些类型的转换,编译器可以隐式地自动进行,这种转换称为自动类型转换;
而有些类型转换需要程序员显式指明,那么通常把这种转换称为强制类型转换。
自动类型转换
自动转换是在源类型和目标类型兼容以及目标类型广于源类型时发生一个类型到另一类的转换。我们先来看一段代码
//vs2019
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>
int main()
{
//定义一个整型指针变量pPoint
int* pPoint;
//定义基本的数据的类型
char c;
short s;
int i;
long l;
float f;
double d;
//将整型浮点型数据赋值给指针类型
pPoint = c;
pPoint = s;
pPoint = i;
pPoint = l;
pPoint = f;
pPoint = d;
return 0;
}
由于指针变量和整型、浮点这些数据型的类型是不能相互赋值的,编译报错输出:
那么我们把同类型数据类型进行运算后赋值呢?
//vs2019
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>
int main()
{
//定义一个整型指针变量pPoint
int* pPoint;
//定义基本的数据的类型
char c;
short s;
int i;
long l;
float f;
double d;
//将整型浮点型数据运算之后赋值给指针类型
pPoint = c + c;
pPoint = s + s;
pPoint = i + i;
pPoint = l + l;
pPoint = f + f;
pPoint = d + d;
return 0;
}
-
char同类型运算,结果是一个int类型。 -
short同类型运算,结果是一个int类型。 -
int同类型运算,结果是一个int类型。 -
long同类型运算,结果是一个long类型。 -
float同类型运算,结果是一个float类型。 -
double同类型运算,结果是一个double类型。
如下图所示:
同类型运算中:
-
整型:比int小的,都会转换成int,比int大的不变。 -
浮点:不变。
那么我们把不同类型数据类型进行运算后赋值呢?
//vs2019
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>
int main()
{
//定义一个整型指针变量pPoint
int* pPoint;
//定义基本的数据的类型
char c;
short s;
int i;
long l;
float f;
double d;
//将整型浮点型数据混合运算赋值给指针类型
pPoint = c + s; // char + short = int
pPoint = c + i; // char + int = int
pPoint = c + l; // char + long = int
pPoint = c + f; // char + float = long
pPoint = c + d; // char + double = float
return 0;
}
-
char类型与short类型运算,结果是一个int类型。 -
char类型与int类型运算,结果是一个int类型。 -
char类型与long类型运算,结果是一个long类型。 -
char类型与float类型运算,结果是一个float类型。 -
char类型与double类型运算,结果是一个double类型。
结果如下图所示:
可以得出在不同类型运算中:
-
如果两边均比int小或等于int,那么结果为int。 -
如果两边有比int大的,那么结果为比int大的类型。
我们得到结论如图:
-
整型类型级别从低到高依次为:
int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long
-
浮点型级别从低到高依次为:
float -> double
自动转换规则:
-
图中 横向箭头表示必须的转换,如两个float型数参加运算,虽然它们类型相同,但仍要先转成double型再进行运算,结果亦为double型。 -
图中 纵向箭头表示当运算符两边的运算数为不同类型时的转换,如一个long 型数据与一个int型数据一起运算,需要先将int型数据转换为long型, 然后两者再进行运算,结果为long型。 -
当 较高类型的数据转换为较低类型时, 则可能有些数据丢失。 -
当 较低类型的数据转换为较高类型时,一般只是形式上有所改变, 而不影响数据的实质内容。 -
所有这些转换都是由系统自动进行的,使用时你只需从中了解结果的类型即可。
强制类型转换
强制类型转换是通过类型转换运算来实现的。其一般形式为:
(类型说明符) (表达式)
其作用就是把表达式的运算结果强制转换成类型说明符所表示的类型的值。
//vs2019
//来源:技术让梦想更伟大
//作者:李肖遥
#include<stdio.h>
#include<string.h>
int main()
{
float f,x=1.3,y=1.4;
int i = 4,a,b;
a = x + y;
b = (int)(x+y);
f = 10/i;
printf("a=%d,b=%d,f=%f,x=%f,y=%f\n",a,b,f,x,y);
}
运行结果如下:
我们从中可以看到,虽然x,y变强制转换int型,但是最后输出的值不变,强制类型转换没有影响x和y变量原本的类型。而上图警告已经说明了一切。
注意:在C语言中,对一个变量赋值的时候,这个变量初始定义的类型包含了两层含义:
-
这个数据类型表示的内存空间的大小。 -
编译器把设定的数值放到这个内存空间,是数据类型的存储方式解析后存进去的。
总结强调一点
进行强制类型转换后,内存空间里面的内容是不会发生改变的,改变的是运算时的临时数据对象的类型,是你去读取这个内存空间时的解析方法。所以,一定要对这个数据类型的内存空间和解析方式有一个清晰的认知。
嵌入式编程专辑 Linux 学习专辑
C/C++编程专辑
Qt进阶学习专辑
关注 微信公众号『技术让梦想更伟大』,后台回复“m”查看更多内容,回复“ 加群 ”加入技术交流群。
长按前往图中包含的公众号关注
本文分享自微信公众号 - 技术让梦想更伟大(gh_f7effb2fbc1c)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
nodejs可读流源码分析
可读流是对数据消费的抽象,nodejs中可读流有两种工作模式:流式和暂停式,流式就是有数据的时候就会触发回调,并且把数据传给回调,暂停式就是需要用户自己手动执行读取的操作。我们通过源码去了解一下可读流实现的一些逻辑。因为实现的代码比较多,逻辑也比较绕,本文只分析一些主要的逻辑,有兴趣的可以参考文档或者自行深入看源码了解细节。我们先看一下ReadableState,这个对象是表示可读流的一些状态和属性的。 functionReadableState(options,stream){options=options||{};//是否是双向流varisDuplex=streaminstanceofStream.Duplex;//数据模式this.objectMode=!!options.objectMode;//双向流的时候,设置读端的模式if(isDuplex)this.objectMode=this.objectMode||!!options.readableObjectMode;//读到highWaterMark个字节则停止,对象模式的话则是16个对象this.highWaterMark...
- 下一篇
52.1 AP!RepPoints V2:用于目标检测的验证+回归,刚刚开源!
点击关注上方“AI深度视线”,并“星标”公号 技术硬文,第一时间送达! AI视线 将验证和回归进行组合,是目前最强的Anchor-free目标检测网络,与前几天的AutoAssign并列。 论文链接: https://arxiv.org/abs/2007.08508 代码昨天前刚刚开源! https://github.com/Scalsol/RepPointsV2 作者团队:MSRA&北京大学 1 摘要 验证和回归是神经网络中用于预测的两种通用方法。每种方法都有其各自的优势:验证更容易准确推断,回归更有效并且适用于连续目标变量。因此,仔细地组合它们以利用它们的好处通常是有益的。 在本文中,我们采用了这种理念来改进最新的对象检测,特别是通过RepPoints。尽管RepPoints提供了高性能,但我们发现它严重依赖于回归来进行目标定位,因此还有改进的余地。 我们将验证任务引入RepPoints的位置预测中,从而生成RepPointsv2,它使用不同的主干和训练方法,在COCO对象检测基准上比原始RepPoints一致地提高了约2.0 mAP。RepPoints v2还可以通过单个...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS6,CentOS7官方镜像安装Oracle11G
- Windows10,CentOS7,CentOS8安装Nodejs环境