0%

INT_MAX和INT_MIN

今天Leetcode的每日一题是实现一个atoi函数,其中要求当参数大于INT_MAX或小于INT_MIN时返回INT_MAX或INT_MIN。做题时突然发现自己对如何通过位运算得到INT_MAX和INT_MIN还一知半解,因此决定探索一下。

前置知识

  • int在C/C++中的字节数

    int具体所占的字节数和平台有关,标准的说法是不短于short,不长于long。在目前使用的大部分平台中通常都是4个字节,即32位。因此本文按32位分析。

  • 原码

    最高位是符号位,0表示正,1表示负,其他位是数字的绝对值的二进制。

    例如:

    1 的原码:00000000 00000000 00000000 00000001

    -1 的原码:10000000 00000000 00000000 00000001

  • 反码

    正数的反码与原码一致,负数的反码在原码的基础上保持符号位不变,其他位按位取反。

    例如:

    -1 的反码:11111111 11111111 11111111 11111110

  • 补码

    正数的补码与原码一致,负数的补码是其反码加1

    例如:

    -1 的补码:11111111 11111111 11111111 11111111

INT_MAX和INT_MIN的值

计算机中的数字都使用补码表示,原因是为了“化减为加”,只需要实现一个加法器就可以同时完成加和减两种运算。int是带符号整数,只有31位可以表示数字,因此就可以得到

INT_MAX: 01111111 11111111 11111111 11111111,即 $2^{31}-1$

INT_MIN: 10000000 00000000 00000000 00000000,即 $-2^{31}$

以上均为补码表示,注意到INT_MIN的原码和补码是一致的,且从原码的定义看,INT_MIN应该表示“负0”才对,但由于我们不需要两个0,因此人为规定补码10000000 00000000 00000000 00000000表示 $-2^{31}$。

同时根据补码的运算规则可以发现的一个规律是:

同理:

INT_MAX和INT_MIN的获得

有了上面的分析,就可以定义INT_MAX和INT_MIN了。

1
2
3
4
5
6
7
8
9
// 方法一:16进制硬编码
const int INT_MAX = 0x7fffffff;
const int INT_MIN = 0x80000000;

// 方法二:利用无符号整型和公式
const int INT_MAX = ((unsigned)(-1)) >> 1;
const int INT_MIN = INT_MAX + 1;

// 方法三:climits/limitis.h头文件中已定义,可直接使用