这里到底发生了什么?输出现在为“False”:
#include <stdio.h>
int main()
{
if (sizeof(int) > any_negative_integer)
printf("True");
else
printf("False");
return 0;
}
如果我将其更改为:
if (sizeof(int) < any_negative_integer)
输出为“True”。
更新:same question已被询问,我在询问之前找不到它。
答案 0 :(得分:27)
sizeof返回size_t
,这是无符号的,因此-1
正在转换为非常大的无符号数。使用正确的警告级别会对此有所帮助,clang
使用-Wconversion
或-Weverything
( note this is not for production use )标记警告我们:
warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
if (sizeof(int) > -1)
~ ^~
对于gcc
,您会收到使用-Wextra
标记的类似警告:
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (sizeof(int) > -1)
^
作为参考,我们知道来自draft C99 standard部分7.17
公共定义的 size_t unsigned ,其中说明:
size_t
这是sizeof运算符的结果的无符号整数类型; [...]
注意,它没有指定关于该类型的任何其他内容,在我的特定情况下,它恰好是 unsigned long ,但它不一定是。
-1
的转换是由6.3.1.8
常规算术转换部分中涵盖的通常的算术转换引起的,其中包含:
[...]
否则,如果具有无符号整数类型的操作数的等级大于或等于 等于另一个操作数的类型的等级,然后是操作数 有符号整数类型转换为带有unsigned的操作数的类型 整数类型。
否则,如果带有符号整数类型的操作数的类型可以表示 那么,带有无符号整数类型的操作数类型的所有值 具有无符号整数类型的操作数将转换为该类型 带有符号整数类型的操作数。
否则,两个操作数都将转换为无符号整数类型 对应于带有符号整数类型的操作数的类型。
所以唯一的时间-1
不会被转换为无符号值,如果 int 可以表示 size_t 的所有值,这不是案例在这里。
为什么-1
最终成为一个大的无符号值,实际上它最终成为无符号类型的最大值是由于6.3.1.3
符号和无符号整数其中说:
否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内。 49)
所以我们最终得到:
-1 + (UMAX + 1)
是:
UMAX
因此最终得到:
if (sizeof(int) > UMAX )
答案 1 :(得分:2)
由于sizeof()
返回size_t
,因此为无符号类型。由于在比较之前隐式转换,比较有符号和无符号类型可能会产生令人惊讶的结果。