C/C++整数的范围

我们经常要接触的整型数的范围,比如signed char的范围是-128~127,signed short的范围是-32768~32767。

这里将要告诉你,是怎么计算出来的。


拿signed char来说明一下:

因为是有符号的整数,最高位为符号位

1.对于正数,最大值的二进制表示为: 0111  1111

    计算出它的值: (1 << 7) - 1 = 127, 没有问题


2.对于负数

  最小值的二进制表示为: 1111  1111

  计算出它的值: -127,  有问题,怎么不是-128?

  现在先告诉大家,后面详细说明: 最小的负数表示不是 【1111  1111】 而是【1000 0000】,而计算机规定signed char 情况下【1000 0000】的值为-128;

  -127 也不是用【1111 1111】原码表示, 而是用其补码【1000 0001】表示的。



  要弄清楚这个问题, 就要引入计算机的字节编码的概念,  原码,反码和补码的概念。

 一开始的时候,计算机只支持原码的。

原码是指一个二进制数左边加上符号位后所得到的码,且当二进制数大于0时,符号位为0;二进制数小于0时,符号位为1。

但是存在问题, 举例说明:

1 + 2= 3

(0000 0001)原 + (0000 0010)原 = (0000 0011)原  => 3


1 - 1 = 0

(0000 0001)原  + ( 1000  0001)原 = (1000 0010)原  => -2

1减去1的值应该等于0 的, 但是转换成1 和 -1的原码加法运算的值是-2,明显错误。


所以,计算科学中就引入了反码和补码的概念, 非负数用原码表示, 负数用补码表示。现在的计算机99.99999999999999%是补码表示。

反码: 正数和0的反码是其本身;负数保持符号位不变,其它各位求反(1变0, 0变1)

补码: 整数和0的补码是其本身, 负数的补码是其原码的反码,再加上1得到的数值。

补码与补码  或者 补码和原码,看作是补码,得到原码的过程求反再加1

现在再看一下 1减去1的例子:

(0000 0001)原 + (1111 1111)补  =  (0000 0000)补  => 0 

值是0, 正确了。


但是有一个特殊的补码 【1000 0000】,计算机规定其值为-128,因为计算机中0是看作正整数的,其反、补码都一样,故【1000 0000】没有其它成员使用。

此处是1个字节的有符号整数, 其它的如short, int, long long类型,计算机也是相似的处理, 把符号位为1,其他位为0的看作是最小值(最大值加1的负数)



============================

通过以上的学习,现在可以轻松计算出,8位,16位, 32位, 64位有符号整数的范围了。

我用C语言简单实现

#include <stdio.h>
#include <stdint.h>
#define MAX_INT8    0x7f
#define MIN_INT8    ((int8_t)0x80)
#define MAX_UINT8   0xff

#define MAX_INT16   0x7fff
#define MIN_INT16   ((int16_t)0x8000)
#define MAX_UINT16  0xffff

#define MAX_INT32   0x7fffffff
#define MIN_INT32   ((int32_t)0x80000000)
#define MAX_UINT32  0xffffffff

#define MAX_INT64   0x7fffffffffffffff
#define MIN_INT64   ((int64_t)0x8000000000000000)
#define MAX_UINT64  0xffffffffffffffff


int main(int argc, char *argv[])
{
    printf("max_int8  = %d\n", MAX_INT8);
    printf("min_int8  = %d\n", MIN_INT8);
    printf("max_uint8 = %u\n", MAX_UINT8);


    printf("max_int16  = %d\n", MAX_INT16);
    printf("min_int16  = %d\n", MIN_INT16);
    printf("max_uint16 = %u\n", MAX_UINT16);


    printf("max_int32  = %d\n", MAX_INT32);
    printf("min_int32  = %d\n", MIN_INT32);
    printf("max_uint32 = %u\n", MAX_UINT32);


    printf("max_int64  = %lld\n", MAX_INT64);
    printf("min_int64  = %lld\n", MIN_INT64);
    printf("min_uint64 = %llu\n", MAX_UINT64);

    return 0;
}

运行结果:

max_int8  = 127
min_int8  = -128
max_uint8 = 255
max_int16  = 32767
min_int16  = -32768
max_uint16 = 65535
max_int32  = 2147483647
min_int32  = -2147483648
max_uint32 = 4294967295
max_int64  = 9223372036854775807
min_int64  = -9223372036854775808
min_uint64 = 18446744073709551615


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值