与负数相比,为什么sizeof运算符会发生这种情况?
这里真的发生了什么? 现在的输出是“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)
输出是“真”。
更新: 同样的问题已经被问到,我找不到之前问。
sizeof返回size_t
,它是无符号的,所以-1
被转换成非常大的无符号数。 使用正确的警告级别在这里会有所帮助,用-Wconversion
或-Weverything
( 注意这不是用于生产用途 )标志警告我们:
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) ^
作为参考,我们知道size_t是从C99标准草案 7.17
草案中 未签名的 。
size_t
这是sizeof运算符结果的无符号整数types; […]
注意,它没有指定types的任何其他内容,在我的具体情况下它恰好是无符号的长整型,但不一定是。
-1
的转换是由于6.3.1.8
常见的算术转换引起的。
[…]
否则,如果具有无符号整数types的操作数的级别大于或等于另一操作数的types的级别,则将具有有符号整数types的操作数转换为具有无符号整数types的操作数的types。
否则,如果具有有符号整数types的操作数的types可以表示具有无符号整数types的操作数types的所有值,则将具有无符号整数types的操作数转换为具有有符号整数types的操作数的types。
否则,两个操作数都转换为与带符号整数types的操作数types相对应的无符号整数types。
所以唯一的时间-1
不会被转换成一个无符号的值将是如果int可以代表size_t的所有值,这不是这里的情况。
为什么-1
最后是一个很大的无符号值,实际上它是无符号types的最大值,这是由于6.3.1.3
节的有符号和无符号整数 ,它们表示:
否则,如果新types是无符号的,则通过重复地增加或减去新types中能够表示的最大值之一来转换该值,直到该值在新types的范围内。 49)
所以我们结束了:
-1 + (UMAX + 1)
这是:
UMAX
并因此最终:
if (sizeof(int) > UMAX )
因为sizeof()
返回一个size_t
,一个无符号types。 比较有符号types和无符号types会导致令人惊讶的结果,因为在比较之前进行隐式转换。