两个表达式都为TRUE

时间:2015-08-31 13:42:18

标签: c

在第一个代码块中,两个条件都保持为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 !!!

2 个答案:

答案 0 :(得分:3)

因为-2适合int16_t,而-2uint16_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的强制转换。否则,有很多事情可能会出错。