【问题标题】:unsigned becomes signed in if-statement comparisons?unsigned 在 if 语句比较中变成有符号的?
【发布时间】:2010-11-17 12:27:25
【问题描述】:

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

以下代码的问题是第一个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 也能正常工作?

【问题讨论】:

标签: c comparison if-statement unsigned


【解决方案1】:

在表达式中:

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

(u16_varLow - u16_varHigh) 将提升为 int 并计算为 -65525。解决您的问题的方法是强制转换为无符号类型,就像您在“Does enter”代码中所做的那样。

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

【讨论】:

  • 实际上是u16_varLowu16_varHigh在减法之前分别提升为int
  • 是否完成了两个单独的演员表?将不输入以下 if 语句: u16_varHigh = 0xff00;
    if( u16_varHigh
  • 还值得注意的是(unsigned short) 没有效果(在 32 位机器上)。如果unsigned short 的所有值都适合int,则(unsigned short)5 在被视为比较输入之前被提升为int。如果您在 short 和 int 宽度相同的处理器上执行此操作,(unsigned short)5 将提升为 unsigned,lhs 也会如此,并且条件为真。
  • @Wilmer 我不太关注你,但我认为你误解了。示例中的“两个无符号之间的差异”实际上是两个整数之间的差异,因为在考虑减法之前,u16 都被转换为整数。如果您改为使用(unsigned)u16_varLow-(unsigned)u16_varHigh,则减法的结果将是无符号的。
【解决方案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 是一个无符号类型,并且无符号类型的算术是以适当的二的幂为模。

【讨论】:

    【解决方案3】:

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

    这正是您所看到的 - u16_varLowu16_varHigh(unsigned short)5 在减法和比较之前都被提升为 int,然后使用 int 发生。如果您希望确定一个表达式将使用无符号算术,您必须在 unsigned int 中进行,not unsigned short:

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

    【讨论】:

      【解决方案4】:

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

      注意 - 你知道这一切都依赖于平台,对吧? shortint等的大小视具体平台而定。

      【讨论】:

      • @注意:我知道这一点,但无论如何我还是谢谢你(因为我知道这一点,你会为我节省很多工作)
      猜你喜欢
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-01
      相关资源
      最近更新 更多