我的电脑认为signed int小于-1?

Jah*_*Jah 3 c unix linux casting

#include <stdio.h>
int main(void)
{
    printf("%d", sizeof(signed int) > -1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果为0(FALSE).怎么会这样?我使用64位ubuntu linux,所以结果应该是(4> -1)=> 1 => True.

cni*_*tar 10

事情是sizeof操作员返回无符号数量(size_t).因此,比较促进-1了无符号,这使它看起来像一个非常大的数字.

你可以试试:

printf("%d", ((int)sizeof(signed int)) > -1);
Run Code Online (Sandbox Code Playgroud)


zwo*_*wol 8

sizeof(signed int)有类型size_t,这是一个无符号类型.当您在有符号值和无符号值之间进行比较[并且无符号值的类型至少与有符号值的类型一样大]时,在比较之前将有符号值转换为无符号值.此转换导致-1成为无符号类型的最大可能值.换句话说,就好像你写的那样

#include <limits.h>
/* ... */
printf("%d", sizeof(signed int) > SIZE_MAX);
Run Code Online (Sandbox Code Playgroud)

当你犯这个错误时,你可以让gcc警告,但是默认情况下它甚至没有打开-Wall:你需要-Wextra或者更具体-Wsign-compare.(这个警告产生很多误报,但我认为打开新代码很有用.)

  • 它与两个补码无关.`(size_t)-1 == SIZE_MAX`. (2认同)
  • 从技术上讲,即使当一个操作数*是*无符号时,signed*总是*被提升为无符号也不是真的,参见6.3.1.8(1),只有当签名类型不大且能够代表全部时才会发生这种情况(可能更小的)无符号操作数的可能值. (2认同)

Dig*_*oss 5

整数促销

C中有许多隐式转换,它特别有助于理解所谓的"通常的算术转换",其中包括所谓的整数提升.1

实际规则有点复杂,但是,简化后,当运算符具有不同类型的操作数时,所有标量类型都会自动转换.转换首先采用较低等级的操作数并将其转换为较高等级的类型.然后,如果只有一个操作数被签名,则它将被转换为无符号,除非带有有符号类型的操作数更大并且可以表示所有无符号类型的值.您的示例不是这种情况,因为size_t几乎总是大于或大于int.

最后,在几乎所有机器上,-1都设置了所有位,使其成为无符号时非常大的数字.


1. ISO/IEC 9899:1999 ("C99") 6.3转换