C语言的最小整数问题
by yuanyi
at 2011-09-12 22:03:00
original http://item.feedsky.com/~feedsky/heikezhi/~8608072/564698634/6713895/1/item.html
当我尝试向WCRT(一个针对VC++的轻量级C运行库)中添加几个头文件时,我发现了一个很有趣的事情。
<limits.h>中定义了一个表示int类型的最小值的宏INT_MIN,在我目前使用的32位编译器中,它的定义如下:
#define INT_MIN (-2147483647 - 1)
为什么不直接定义成-2147483648吗?
首先,我们需要明确,-2147483648并不是一个常量,让我们来看看标准是怎么说的:
“一个整数常量是指以数字开始,并且不包含小数点或是指数部分,它可能会包含一个表示进制的前缀以及一个表示类型的后缀“
你应该注意到,这里没有提到符号,所以 -2147483648实际上是一个由一个一元减号运算符和一个整数常量2147483648构成的常量表达式。
但是这依然没有解释为什么宏不直接使用这个表达式,要明白这个原因,我们需要来重新看看关于整形的类型定义。
一个没有后缀的整形常量会按照下面顺序进行匹配:
C89: int, long int, unsigned long int
C99: int, long int, long long int
C++: int, long int, long long int
问题就在这里,2147483648超出了32位有符号整数的表示范围,所以它要么被当成一个无符号长整数(unsigned long int)或者就变成一个有符号的超长整数(long long int)。
因此这里我们使用了一点小技巧来表示-2147483648,这也就是为什么它会被定义成(-2147483647 – 1)了,这样,INT_MIN就能确保它返回的是一个32位的有符号整数(32-bit signed integer)。
但是如果你去标准中查找INT_MIN的定义,你会看到,它是这样定义的:
INT_MIN -32767
问题来了,为什么不是 (-32767 – 1)呢?
这是因为虽然当今的大部分电脑都使用2进制来表示有符号数,但是情况并不总是这样。
因为C语言的设计宗旨是在各种架构上都能高效的运行,所以标准出于支持其它表示的考虑对limit做了如上定义。
最后让我用一个例子来作为这篇帖的结束,试试编译下面的C程序,并告诉我它在你机器上的执行结果,是不是不可思议?
#include <stdio.h> #include <limits.h> #include <float.h> int main(void) { if (-2147483648 > 0) printf("positive\n"); if (-2147483647-1 < 0) printf("negative\n"); if (INT_MIN == -INT_MIN) printf("equal\n"); if (FLT_MIN > 0) printf("floating\n"); return 0; }
-------
本文来自"Hard to C"
想和我们一道传播黑客精神?快来加入吧!
无觅猜您也喜欢: | |||
Traceur: 体验下一代Javascript语言 |
最快的编程语言是? |
你在解决错误的问题 |
想去MongoDB工作?解决这个问题 |
无觅 |