首页 文章

无符号和有符号整数的比较运算

提问于
浏览
34

请参阅此代码段

int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}

这给出了输出:a是SMALL:1001

我不明白这里发生了什么 . >运算符如何在这里工作?为什么“a”小于“b”?如果它确实更小,为什么我得到一个正数(1001)作为差异?

7 回答

  • 0

    硬件旨在将签名与签名和无符号进行比较 .

    如果需要算术结果,请先将无符号值转换为更大的有符号类型 . 否则编译器将假设比较实际上是无符号值之间的比较 .

    并且-1表示为1111..1111,因此它的数量非常大......最大...当被解释为无符号时 .

  • 0

    同时比较a> b,其中a是无符号int类型,b是int类型, b is type casted to unsigned int so,signed int value -1转换为无符号**的MAX值(范围:0到(2 ^ 32)-1)**因此,a> b ie,(1000> 4294967296)变为假 . 因此,执行了循环 printf("a is SMALL! %d\n", a-b); .

  • 44

    您正在进行无符号比较,即比较1000到2 ^ 32 - 1 .

    由于printf中的%d,输出已签名 .

    注:有时混合有符号和无符号操作数时的行为是特定于编译器的 . 我认为最好避免它们,并在有疑问时进行演员表演 .

  • 13
    #include<stdio.h>
     int main()
     {
       int a = 1000;
       signed int b = -1, c = -2;
       printf("%d",(unsigned int)b);
       printf("%d\n",(unsigned int)c);
       printf("%d\n",(unsigned int)a);
    
       if(1000>-1){
          printf("\ntrue");
       }
       else 
         printf("\nfalse");
         return 0;
     }
    

    为此,您需要了解运算符的优先级

    • 关系运算符从左到右工作......所以当它到来时

    如果(1000> -1)

    然后首先它会将-1更改为无符号整数,因为int默认被视为无符号数,并且它的范围大于有符号数

    -1将变为无符号数,它变为非常大的数字

  • 0

    找到一种简单的比较方法,当你无法摆脱无符号声明时(例如,[NSArray count]),只需将“unsigned int”强制为“int”即可 .

    如果我错了,请纠正我 .

    if (((int)a)>b) {
        ....
    }
    
  • -1

    不同整数类型之间的二进制操作在由所谓的通常算术转换定义的"common"类型内执行(参见语言规范,6.3.1.8) . 在您的情况下,"common"类型是 unsigned int . 这意味着 int 操作数(您的 b )将在比较之前转换为 unsigned int ,以及执行减法的目的 .

    -1 转换为 unsigned int 时,结果是最大可能的 unsigned int 值(与 UINT_MAX 相同) . 不用说,它会比你的无符号 1000 值更大,这意味着 a > b 确实是假的, a 确实比 (unsigned) b 小 . 代码中的 if 应解析为 else branch,这是您在实验中观察到的 .

    相同的转换规则适用于减法 . 您的 a-b 实际上被解释为 a - (unsigned) b ,结果类型为 unsigned int . 无法使用 %d 格式说明符打印此值,因为 %d 仅适用于有符号值 . 您尝试使用 %d 打印它会导致未定义的行为,因此从C语言的角度来看,您看到的打印值(即使它在实践中具有逻辑确定性解释)完全没有意义 .

    Edit: 实际上,我对未定义的行为部分可能是错的 . 根据C语言规范,相应的有符号和无符号整数类型范围的公共部分应具有相同的表示(暗示,根据脚注31,"interchangeability as arguments to functions") . 因此,如上所述, a - b 表达式的结果是无符号 1001 ,除非我遗漏了某些内容,否则使用 %d 说明符打印此特定无符号值是合法的,因为它落在 int 的正范围内 . 使用 %d 打印 (unsigned) INT_MAX + 1 将是未定义的,但 1001u 很好 .

  • 0

    int 为32位的典型实现中,转换为 unsigned int 时的-1为4,294,967,295,其确实≥1000 .

    即使你在 unsigned 世界中对待减法, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001 就是你得到的 .

    这就是 gcc 在将 unsignedsigned 进行比较时会发出警告的原因 . (如果没有看到警告,请传递 -Wsign-compare 标志 . )

相关问题