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.

时间: 2024-11-01 10:43:25

Why define INT_MIN (-INT_MAX - 1)的相关文章

【译】为什么这样宏定义#define INT_MIN (-2147483647 - 1)?

2的32次方为2147483648*2,0~(2147483648*2-1)这是32位机上无符号整数代表的范围.而32机的int范围为-2147483648~+2147483647 stackoverflow.com上有人提出这样一个问题: if (-2147483648 > 0) std::cout << "true"; else std::cout << "false"; 这将输出true,而下面的程序会输出false: if (i

C语言中内存分配

C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重点介绍C程序中内存的分配,以及C语言编译后的可执行程序的存储结构和运行结构,同时还介绍了堆空间和栈空间的用途及区别. 第2节主要介绍C语言中内存分配及释放函数.函数的功能,以及如何调用这些函数申请/释放内存空间及其注意事项. 3.1 内存管理基本概念 3.1.1 C程序内存分配 1

《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量. 通过cat 命令查看: [email protected]:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software

LeetCode #Reverse Number#

刚背了单词,然后做个题玩玩-挑个软柿子踩踩-哈哈 很简单的思路.不过好玩的是我忘记检查处理完的数据是否符合整形数据返回了.因而好一会儿不能AC. 感谢 @Fantasy. 很快的指出我没有检查返回数据的范围. 先给出我超丑陋的解(python), 而后给出其他高手给出的很优雅的解!!也是用python 最后会给出利用java和C/C++的解. """ Programmer : EOF Date : 2015.03.31 File : reverse_interger.py &

Linux int 最大为多大

可以查看 /usr/include/limits.h 文件 里面定义好了各种类型的最大最小值 ... /* Minimum and maximum values a `signed int' can hold.  */#  define INT_MIN   (-INT_MAX - 1)                                                                                                           

C语言中内存分配 (转)

在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重点介绍C程序中内存的分配,以及C语言编译后的可执行程序的存储结构和运行结构,同时还介绍了堆空间和栈空间的用途及区别. 第2节主要介绍C语言中内存分配及释放函数.函数的功能,以及如何调用这些函数申请/释放内存空间及其注意事项. 3.1 内存管理基本概念 3.1.1 C程序内存分配 1.C程序结构 下面

c语言中TMin的写法

在<CSAPP>中提到: #define INT_MAX 2147483647 #define INT_MIN (-INT_MAX -1) INT_MIN这样写的原因是: 虽然-2147483648 这个数值能够用int类型来表示,但在C语言中却没法写出对应这个数值的int类型常量. 因为按照c语言的类型推导,-2147483648被写成常量形式的时候,对于c90,其会转成unsigned类型来表示为2147483648,对于c99,其会被表示为long long类型,值为-214748364

【转】C语言中内存分配

原文:C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重点介绍C程序中内存的分配,以及C语言编译后的可执行程序的存储结构和运行结构,同时还介绍了堆空间和栈空间的用途及区别. 第2节主要介绍C语言中内存分配及释放函数.函数的功能,以及如何调用这些函数申请/释放内存空间及其注意事项. 3.1 内存管理基本概念 3.1.1 C程序内存分

链表系列文章(一)

参考 http://www.cnblogs.com/skywang12345/p/3561803.html在此致谢! 采用C++,实现了单链表和双向循环链表: 1. 单链表 1 #ifndef SINGLE_LIST_H 2 #define SINGLE_LIST_H 3 4 #ifndef INT_MAX 5 #define INT_MAX 2147483647 6 #define INT_MIN (-INT_MAX - 1) 7 #endif 8 #define ERROR INT_MIN