3

我想知道以下代码输出的原因是什么:

unsigned short a=10,aa=-1;
if(a>-1)
  printf("surprise");
else 
  printf(" No surprise");

这给出了输出“惊喜”

 unsigned int a=10,aa=-1;
    if(a>-1)
      printf("surprise");
    else 
      printf("No surprise");

这给出了输出“No Surprise”

unsigned short a=10,aa=-1;
if(a>aa)
   printf("surprise");
else 
  printf("No surprise");

这给出了输出“No Surprise”

4

3 回答 3

2

其整数提升用 C 语言指定。基本上,算术是有符号的而不是短的。我假设您使用 32 位及以上的 CPU。

unsigned short a=10,aa=-1;
if(a>-1)
  printf("surprise");
else 
  printf(" No surprise");

上面的转换成下面的汇编。因此,您得到的是有符号 int(10) 与有符号 int (-1) 的比较,正如汇编程序使用 jle 指令所指示的那样。

unsigned short a=10,aa=-1;
000C17DE  mov         eax,0Ah  
000C17E3  mov         word ptr [a],ax  
000C17E7  mov         eax,0FFFFh  
000C17EC  mov         word ptr [aa],ax  
    if(a>-1)
000C17F0  movzx       eax,word ptr [a]  
000C17F4  cmp         eax,0FFFFFFFFh  
000C17F7  jle         wmain+52h (0C1812h)

至于第 2 部分,它无符号地将 0x0A 与 0xFFFFFFFF 进行比较。对于第 3 部分,它签名比较 0x0A 和 0xFFFF

于 2013-09-28T13:16:39.627 回答
2

请参阅此堆栈交换问题:

在存在 unsigned int 和 signed int 的 C 表达式中,哪种类型将提升为哪种类型?

在 AProgrammer 的响应中,列出了完整的规则。在您的第一种情况下,适用第 4 条规则(-1 是有符号整数,它可以表示 unsigned short 的所有值,因此 unsigned short 被提升为有符号整数)。在第二种情况下,适用第三条规则(有符号整数不能代表无符号整数的所有值,因此将其更改为无符号整数)。在您的第三种情况下,-1 被转换为 unsigned short,然后应用第一条规则。

一般来说,我喜欢通过在进行任何比较之前将所有变量转换为相同的有符号类型(大到足以容纳我期望的范围)来避免混淆。

于 2013-09-28T14:04:28.843 回答
1

您正在将一个无符号变量初始化为 -1。无符号变量只能表示非负数。C 没有指定负符号数的表示形式,因此当您为无符号变量分配负数时,您会调用未定义的行为。此时,程序可以打印“惊喜”、“没有惊喜”或“生日快乐”。

在 2s 补码机器(大多数现代 CPU 都是)上,-1 具有与最大无符号值相同的位表示,因此您可能已将 aa 初始化为最大可表示值。如果那是您真正想要的,则应改为使用 aa = USHRT_MAX。

于 2013-09-28T13:45:58.213 回答