Why define INT_MIN (-INT_MAX - 1)

C语言定义INT_MIN和INTMAX如下:

#define INT_MAX     2147483647

#define INT_MIN      (-INT_MAX - 1)

为什么不直接定义INT_MIN为-2147483648呢?

如果你运行如下代码:

if (-2147483648 > 0)
    printf(“TRUE”);
else
    printf(“FALSE”);

你可能会发现令你意想不到的结果。这是为什么呢?

因为-2147483648不是一个数字,而是一个表达式:一个正值2147483648,前面有个操作符 - 。2147483648超过了int范围的最大正值。如果编译平台的long int类型比int的范围更大,编译器会自动假设2147483648是long int。这会使-2147483648是long int类型,它是一个负数,小于0。但是如果long int和int的范围一样,或者说编译平台没有其他int类型的范围比int大,这意味着2147483648超过了int的范围,导致程序的行为是未定义的。

实际上由于程序的行为是未定义的,2147483648可能被编译器解释为负数,前面的负号使得-2147483648大于0。

为什么定义INT_MIN为(-INT_MAX - 1)能解决问题呢?

-INT_MAX(即-2147483647)的十六进制为0x8001,(-INT_MAX - 1)正好是0x8000,即-2147483648。

下面是相关的一段程序:

/*
 * Description:
 * INT_MIN related curiosities.
 */

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>

#define btoa(x) ((x) ? "TRUE" : "FALSE")

int main()
{
  int a = -2147483648;
  int b = 2147483648;

  printf("-2147483647 > 0 is %s\n", btoa(-2147483647 > 0)); // FALSE
  printf("-2147483648 > 0 is %s\n", btoa(-2147483648 > 0)); // Undefined: may TRUE
  printf("INT_MIN-1 > 0 is %s\n", btoa(INT_MIN-1 > 0)); // TRUE: 0x8000-1=0x7999(INT_MAX)>0
  printf("2147483647 > 0 is %s\n", btoa(2147483647 > 0)); // TRUE
  printf("2147483648 > 0 is %s\n", btoa(2147483648 > 0)); // Undefined: may FALSE
  printf("INT_MAX+1 > 0 is %s\n", btoa(INT_MAX+1 > 0)); // FALSE: 0x7999+1=0x8000(INT_MIN)<0
  printf("int(-2147483648) > 0 is %s\n", btoa(a > 0)); // Undefined:
  printf("int(2147483648) > 0 is %s\n", btoa(b > 0)); // Undefined:
  printf("-2147483648L > 0 is %s\n", btoa(-2147483648L > 0)); // if LONG_INT_MAX > INT_MAX: FALSE; else Undefined.
  printf("-2147483648LL > 0 is %s\n", btoa(-2147483648LL > 0)); // FALSE
  printf("abs(INT_MIN) is %d\n", abs(INT_MIN));
}
在不同平台的运行结果如下:

OS X 10.10 Yosemite(x86-64):

-2147483647 > 0 is FALSE

-2147483648 > 0 is FALSE

INT_MIN-1 > 0 is TRUE

2147483647 > 0 is TRUE

2147483648 > 0 is TRUE

INT_MAX+1 > 0 is FALSE

int(-2147483648) > 0 is FALSE

int(2147483648) > 0 is FALSE

-2147483648L > 0 is FALSE

-2147483648LL > 0 is FALSE

Ubuntu 14.04(x86-64):

-2147483647 > 0 is FALSE

-2147483648 > 0 is FALSE

INT_MIN-1 > 0 is TRUE

2147483647 > 0 is TRUE

2147483648 > 0 is TRUE

INT_MAX+1 > 0 is FALSE

int(-2147483648) > 0 is FALSE

int(2147483648) > 0 is FALSE

-2147483648L > 0 is FALSE

-2147483648LL > 0 is FALSE

abs(INT_MIN) is -2147483648

可以看到现在很多系统已经是64bit,所以(-2147483648 > 0 )也没有出错。

不过值得注意的是,abs(INT_MIN)依然还是-2147483648。这是abs的例外:

If the result cannot be represented by the returned type (such as abs(INT_MIN) in an implementation with two's complement signed values), it causes undefined behavior.

posted @ 2016-04-18 10:53  luckysimple  阅读(623)  评论(0编辑  收藏  举报