今天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 | // 方法一:16进制硬编码 |