unsigned在if语句比较中签名?

时间:2010-11-17 12:27:26

标签: c comparison if-statement unsigned

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

以下代码的问题是第一个if - 声明没有发生(“你好”),而第二个(“世界”)则发生。这个我已经解释为在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 - 语句能够正常工作吗?

4 个答案:

答案 0 :(得分:4)

在表达式中:

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

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

s16_Res1 = u16_varLow - u16_varHigh;得出11的原因是减法的结果-65525不适合短路。

答案 1 :(得分:2)

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

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的适当幂为模。

答案 2 :(得分:2)

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

这正是您所看到的 - u16_varLowu16_varHigh以及(unsigned short)5在减法和比较之前都被提升为int,然后使用{{int 1}}。如果您希望确定表达式将使用无符号算术,则必须在unsigned int unsigned short中执行此操作:

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

答案 3 :(得分:1)

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

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