在第一个代码块中,两个条件都保持为TRUE。第二,第一个成立,另一个成立。
int8_t i8 = -2;
uint16_t ui16 = i8;
if(ui16 == -2) //this is TRUE
if(ui16 == 65534) //this is TRUE as well
这是第二种情况:
int8_t i8 = -2;
int16_t i16 = i8;
if(i16 == -2) //this is TRUE
if(i16 == 65534) //this is NOT TRUE !!!
答案 0 :(得分:3)
因为-2
适合int16_t
,而-2
在uint16_t
转换为无符号。
这是明确定义的行为。
来自ISO / IEC 9899(C99标准工作草案)的:
6.3.1.3有符号和无符号整数
...
2否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内。 49)
...
49)规则描述了数学值的算术,而不是给定类型表达式的值
所以,如果我这样做:
uint16_t i = -2;
编译器应该执行:
i = -2 + (USHRT_MAX + 1);
或
i = -2 - (USHRT_MAX + 1);
直到我们得到一个可存储在16位内且没有符号位的值。
不依赖于-2
的等级,而是数学值。
在您的情况下,这应该是:65534
Which it is with gcc. [C ++遵循签名转换的相同规则]
在您的第二部分代码中,您只需将较低级别的值分配给较高级别的变量。
e.g。使用更多的精度来存储相同的数字。
当您检查i16 == 65534
时,您正在从同一部分调用此部分标准:
3否则,新类型已签名且值无法在其中表示;无论是 结果是实现定义的或引发实现定义的信号。
因为65534
不能存储在15位和一个符号位(2 15 - 1)。
所以调用实现定义的行为。
依赖于此的返回值与依赖 undefined 行为一样糟糕,除非您是编译器开发人员。
答案 1 :(得分:1)
在C中,无符号整数总是按照模数(时钟 - 面)算法运算,但有时只有符号整数,不可靠。
一般来说,期望一个数字等于不同的数字是无稽之谈。你不应该这样编写程序。如果您希望-2
之类的数字表现为正无符号值,则应明确编写类似(uint16_t) -2
的强制转换。否则,有很多事情可能会出错。