C语言的最小整数问题

2011-09-13 06:03

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工作?解决这个问题
无觅