现在的位置: 首页 > 综合 > 正文

C语言中数据类型的表示范围

2017年08月07日 ⁄ 综合 ⁄ 共 1316字 ⁄ 字号 评论关闭

问题:sizeof(int) = 2,int的表示范围为什么是-2^15~2^15-1?

答:对于有符号数,最高位为符号位。二进制原码最大值为0111111111111111=2^15-1,最小值为 1111111111111111=-(2^15-1),而0分为+0和-0,即0000000000000000和

1000000000000000。所以,当以二进制原码表示时,int的表示范围是-32767~-0和+0~32767。注意+0等于-0,因而表示范围中不同的数值个数有2^16-1个,比16位二进制能够提供的2^16个编码少1个。

但计算机中是采用二进制补码存储数据的。正数编码不变,即从0000000000000000到0111111111111111,范围是0~2^15-1。负数编码需要把除符号位以后的部分取反加1。

-32767的补码为1000000000000001,-0的补码为0000000000000000。注意到+0和-0在补码系统中的编码是一样的,而16位二进制数可表示2^16个编码,在补码中零的编码只有一个(+0和-0的编码一样),所以补码中会比原码多一个编码出来,这个编码就是1000000000000000。因为任何一个原码都不可能在转成补码时变成1000000000000000,所以,人为规定1000000000000000这个补码编码为-32768。所以,int的表示范围在补码系统中是-32768~32767。

注意,二进制的最小值确实是1111111111111111,只是二进制补码的最小值才是1000000000000000。

下面举几个容易错的例题。

#include <stdio.h>

int main(void) 
{ 
    char ch = 127;
    ch += 1;
    printf("%d\n", ch);		//结果是-128
	
    return 0; 
}

结果为:-128。char的表示范围是-128~127。因为127 + 1 = 128,二进制表示为10000000,对于有符号的ch来说,最高位为1表示负数。

#include <stdio.h>

int main(void) 
{ 
    unsigned char ch = 255;
    ch += 1;
    printf("%d\n", ch);		//结果是0
	
    return 0; 
}

结果为:0。ch = 255在计算机中的存储为:(000....)11111111,(000....)11111111+1 = (000...)0001 00000000,然后再将最后八位二进制截取给ch,由于最后八位全是0,因此ch = 0。

对于unsigned类型来说,编译器必须调整越界值使其满足要求。编译器会将该值对unsigned类型的可能取值数目求模,然后取所得值。例如:8位的unsigned char其取值范围从0到255,将336存储到8位的unsigned char中,则实际赋值为80,因为336 mod 256 = 80。

负数总是超出取值范围,有些语言将负数赋给unsigned类型是非法的,但在C++中是合法的,其结果是该负数对该类型的取值个数求模后的值。例如:将-1赋给8位的unsigned char,结果是255,因为-1 mod 256 = 255。

抱歉!评论已关闭.