#include <stdio.h>
int main(void)
{
printf("%d", sizeof(signed int) > -1);
return 0;
}
结果为 0(假)。怎么会这样?我使用的是 64 位 ubuntu linux,所以结果应该是 (4 > -1) => 1 => True。
问题是sizeof
运算符返回一个无符号数量 ( size_t
)。所以比较提升-1
为无符号,这使它看起来像一个非常大的数字。
你可以试试:
printf("%d", ((int)sizeof(signed int)) > -1);
sizeof(signed int)
有 type size_t
,这是一个无符号类型。当您在有符号值和无符号值之间进行比较时[并且无符号值的类型至少与有符号值的类型一样大],有符号值在比较之前转换为无符号值。此转换导致-1
成为无符号类型的最大可能值。换句话说,就像你写的
#include <limits.h>
/* ... */
printf("%d", sizeof(signed int) > SIZE_MAX);
当你犯这个错误时,你可以让 gcc 发出警告,但默认情况下它不是打开的,甚至在-Wall
: you need-Wextra
或更具体地说是-Wsign-compare
. (这个警告会产生很多误报,但我认为打开新代码很有用。)
C中有许多隐式转换,特别有助于理解所谓的“通常的算术转换”,其中包括所谓的整数提升。1
实际的规则有点复杂,但是,简化后,当运算符具有不同类型的操作数时,所有标量类型都会自动转换。转换首先获取较低级别的操作数并将其转换为较高级别的类型。然后,如果只有一个操作数是有符号的,它将被转换为无符号的,除非具有符号类型的操作数更大并且可以表示所有无符号类型的值。您的示例并非如此,因为 size_t 几乎总是与 int 一样大或更大。
最后,在几乎所有机器上,-1 都设置了所有位,当被视为无符号时,它是一个非常大的数字。
1. ISO/IEC 9899:1999 ("C99") 6.3 转换