一. 数据类型的介绍
本文主要介绍基本类型数据在计算机中的存储方式。char类型的存储和表示本质上还是使用ASCII码值,故放在整型介绍。
二. 整型的存储方式
1. 原码,反码和补码
数据在计算机中是以二进制序列的形式存在,又因为计算的需要产生了原码,反码和补码。
对于正数,它的原码,反码和补码相同。
对于负数,原码:符号位(最高位)为1,其余依次按二进制转换
反码:符号位不变,其余按位取反
补码:反码+1
内存中存储的都是补码。如下:
2. 大小端的存储方式
在上图中可以观察到,-10补码的十六进制序列与在内存中的存储顺序好像是“相反”的,这就涉及到了大小端字节序存储。
大端字节序存储:把一个数据的低位字节放到高地址,高位字节数据放到低地址。
小端字节序存储:把一个数据的低位字节放到低地址,高位字节数据放到高地址。
比如ABCDEFAC这个数据,AB属于高位字节,内存中0x11223344这个地址,11属于低地址。
两种存储方式与编译器的种类有关,可以通过相关的算法程序来判断编译器对数据的存储方式。
3. 整型提升
char类型的打印应该采用%c,但是如果使用了%d,就要涉及到整型提升。
比如
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a = %d , b = %d, c = %d" , a , b , c);
在这个程序中,a,b,c会打印出不同的数值。
b是-1,符合逻辑,这里解释一下a和c为什么是这样的数值。
一个字节是由八个比特位,即八个二进制位组成的。所以,
对于a,
整型a的原码反码和补码是这样的:(按照原码,反码,补码的顺序)
10000000000000000000000000000001
11111111111111111111111111111110
11111111111111111111111111111111
char类型定义a后要进行整型截断,丢失高三个字节的内容,留下11111111
打印时又要进行整型提升,有符号位补符号位,没有补0
于是,a的补码反码和原码序列为
11111111111111111111111111111111
11111111111111111111111111111110
10000000000000000000000000000001
恰好为-1。
对于c,
不同点发生在整型提升,由于c被unsigned修饰,所以没有符号位,需要补零
所以c的补码变为
00000000000000000000000011111111
由于unsigned修饰,原码反码补码相同,所以输出255
4. char类型的取值范围
可以如下依次列出://第一列是补码
00000000 0
00000001 1
00000010 3
00000011 4
...............
0 1111111 127
10000000 -128
10000001 10000000 11111111 -127
...............
1111111 0 11111101 10000010 -2
11111111 11111110 10000001 -1
即-128~127
对于-128的表示,涉及到正零和负零,在二进制编码中,原码和反码是区分正零和负零的,补码不区分。原码中,正零和负零只有符号位不同,在反码中,全零表示正零,全一表示负零。
对于unsigned char类型,由于没有符号,它的表示范围是0~255,即2^8-1
三. 浮点数的存储方式
按照IEEE754的标准,二进制32位(单精度)浮点数和64位(双精度)浮点数的表示如下:
f = (-1)^S * (M) *2^e 其中:e=E-127或1023
其中,
(-1)^S表示符号位,当S=0时,f为正数;当S=1时,f为负数。
M为有效数字,根据科学计数法,其首位必须为1,所以这里舍去1,内存中可以直接存储小数部分,提高精度,大于0,小于1。
2^e表示指数位。
E作为一个阶数,内存中使用的是unsigned int,但使用时可能会出现负数情况,这是就要加上一个中间数,对于32位,这个数是127,对于64位,这个数是1023
输出浮点数时,若E不全为零或不全为1时,用E的计算值减去127,M前添上1.
若E全为零,E=1-127=-126,M前加上0.
若E全为1,数字很大,处理方式同第一条。
以5.5为例:
二进制为 f = 101.1 = 1.011*2^2 = (-1)^0*(1.011)*2^2
S = 0, E = 2, M = 1.011
32位下 S占1bit,E占8bit,M占23bit
64位下 S占1bit,E占11bit,M占52bit
float a = 5.5;
0 10000001 01100000000000000000000