unsigned在if语句比较中签名?

我在这个网站上搜索了一个答案,发现很多对未签名/签名比较的回复,但是这个问题是只比较了无符号参数,但它仍然很有趣。

以下代码的问题是第一个if -statment不会发生(“hello”),而第二个(“world”)就是这样。 我已经解释为在if -statment内部进行的计算会生成一个负数,但是保存到变量的结果完全相同的计算不会(即使结果被保存到有符号变量)。

使用的编译器是gcc 4.4。

 unsigned short u16_varHigh; unsigned short u16_varLow; unsigned short u16_Res1; signed short s16_Res1; u16_varHigh = 0xFFFF; u16_varLow = 10; u16_Res1 = u16_varLow - u16_varHigh; // response is 11 as expected s16_Res1 = u16_varLow - u16_varHigh; // response is 11 as expected // Does not enter if( (u16_varLow - u16_varHigh) > (unsigned short)5 ) { printf( "hello" ); } // Does enter if( (unsigned short)(u16_varLow - u16_varHigh) > 5 ) { printf( "world" ); } 

任何人都可以为我解释这个问题,也许可以找到一个解决方案来解决问题,以便第一个if -statement也能正常工作?

在表达式中:

 if( (u16_varLow - u16_varHigh) > (unsigned short)5 ) 

(u16_varLow - u16_varHigh)将被提升为int并计算为-65525。 您的问题的修复是转换为无符号类型,就像在“输入”代码中一样。

原因s16_Res1 = u16_varLow - u16_varHigh; 收益率11是减法的结果-65525,不适合短期。

在其他答案中我们已经看到了

 u16_varLow - u16_varHigh 

为你(16位short和32位int )相当于

 (int)u16_varLow - (int)u16_varHigh 

因此其结果是int-65525 。 因此,任务

 s16_Res1 = u16_varLow - u16_varHigh; 

相当于

 s16_Res1 = -65525; 

在你的16位short情况下产生“未定义的行为”。 你只是不幸的是你的编译器决定分配11 。 (不幸的是因为我认为最好早点失败。)

与此形成对比

 u16_Res1 = -65525; 

是一个有效的赋值,因为u16_Res1是无符号类型,无符号类型的算术是以2的适当幂为模。

在“通常的算术转换”中,小于int类型在大多数表达式中使用之前会被提升为intunsigned int 。 规则是如果int可以表示较小类型的所有值,那么它将被提升为int ; 否则它被提升为unsigned int 。 这通常被视为疣,因为在许多情况下,它会导致unsigned charunsigned short值被提升为int

这正是你所看到的 – 在减法和比较之前, u16_varLowu16_varHigh以及(unsigned short)5都被提升为int ,然后使用int发生。 如果您希望确定表达式将使用无符号算术,则必须使用unsigned int而不是 unsigned short

 if( ((unsigned)u16_varLow - (unsigned)u16_varHigh) > 5U ) 

第一个, if( (u16_varLow - u16_varHigh) > (unsigned short)5 )永远不会传递,因为(u16_varLow - u16_varHigh)返回负数,因为它被视为整数。 第二个将相同的负数转换为无符号短,这就是它通过的原因。

注意 – 你知道这一切都取决于平台,对吗? shortint等的大小取决于具体平台。