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
类型在大多数表达式中使用之前会被提升为int
或unsigned int
。 规则是如果int
可以表示较小类型的所有值,那么它将被提升为int
; 否则它被提升为unsigned int
。 这通常被视为疣,因为在许多情况下,它会导致unsigned char
和unsigned short
值被提升为int
。
这正是你所看到的 – 在减法和比较之前, u16_varLow
和u16_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)
返回负数,因为它被视为整数。 第二个将相同的负数转换为无符号短,这就是它通过的原因。
注意 – 你知道这一切都取决于平台,对吗? short
, int
等的大小取决于具体平台。