0%

C 隐式类型转换

在项目中遇到一个奇怪的问题,伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
int8_t  a = 0x8F;
uint8_t b = 0x8F;

if( a == b )
{
printf("a = b\n");
}
else
{
printf("a != b, a = %02x, b = %02x\n", a, b);
}

按照我的理解,if(a == b)一定为真。但运行结果却让我大跌眼镜:

a != b, a = ffffff8f, b = 8F

首先,变量a不等于b已经让我吃惊了,然后,打印出来a的值竟然是ffffff8f
查了一通资料,我才知道,原来在 C 语言中有隐式类型转换这么一个规则。
隐式类型转换是指变量在运算中的一种隐式的类型转换,主要分两种:算术赋值转换。

算术转换

算术转换的规则可以用一张图来表示:

1
2
3
4
5
6
7
8
9
10
11
HIGH
^
double <-- float
|
long
|
unsigned
|
int <-- char, short
^
LOW

此图中有两个箭头。

竖向箭头表示不同的数据类型在进行混合运算的时候,会有一个低字节向高字节转换的过程。术语叫寻常算术转换usual arithmetic conversion)。

横向箭头表示不管该类型有没有进行混合运算都势必会进行转换,再进行运算,术语叫整型提升Integral promotions)。

##赋值转换


进行赋值操作时,赋值运算符右边的数据类型必须转换成赋值号左边的类型,若右边的数据类型的长度大于左边,则要进行求余的截取操作。

如定义变量uint8_t a = 257;,因为uint8_t类型的最大值是256,所以要求余的截取操作,最终a = 257 % 256 = 1

又如:

1
2
3
int8_t a = -1;
int32_t b = a;
printf("a = %x, b = %x\n",a, b);

这就是一个扩展操作,a先被转为int,再被转为unsigned,b的十六进制值等于0xFFFFFFFF

回到最开始的那个问题,在==运算中,ab都被隐式地转换成了int型,一个是-113,一个是143,肯定不一样。

prinf的参数实际上也是一种赋值转换,因为%02x指定了参数的类型是uint32_t,所以a被隐式地转换为了uint32_t的类型,也即0xfffffff8

##参考


整型提升

C的隐式类型转换

关于C语言的隐式类型转换

坚持原创技术分享,您的支持将鼓励我继续创作!