整型数据的存储
现代计算机存储和处理的信息以二值信号表示。每个二进制数字,称为位(bit)。
整型数据在编译器中一般以16进制显示,如下:
int main()
{
char a = 10;
short b = 10;
int c = 10;
return 0;
}
图中(0x 00 3D FB XX)表示整型数据的地址,char a是一个字节(byte),地址是(0x 00 3D FB DB),short是两个字节(byte),地址是(0x 00 3D FB CC),int是4个字节(byte),地址是(0x 00 3D FB C0)。
中间(0a 00 00 00)是16进制,转为10进制表示为10。
最后的( . )等一些字符,是所对应的ASCII码值(不做讨论)。
原码、反码、补码
计算机中的整数的二进制有3中表示形式:原码、反码、补码。
内存中存储的是二进制的补码。
整数有正数和负数
- 正数:原码、反码、补码相同。符号位为 0 。
- 负数:符号位为 1 。
原码:按照一个数的正、负直接写出来的二进制。
反码:符号位不变,其他位,按位取反。
补码:反码的二进制序列加一。
例如:
进制 | 数字 | 原码 | 反码 | 补码 | 十六进制 |
---|---|---|---|---|---|
十进制 | 10 | 0000 0000 0000 0000 0000 0000 0000 1010 | ~ | ~ | 0x 00 00 00 0A |
十进制 | -10 | 1000 0000 0000 0000 0000 0000 0000 1010 | 1111 1111 1111 1111 1111 1111 1111 0101 | 1111 1111 1111 1111 1111 1111 1111 0110 | 0x FF FF FF F6 |
为什么要用补码来存储?
因为计算机中只有加法器。比如1-1,在计算机中是1+(-1)。
如果用原码来计算,
数字 | 原码 |
---|---|
1 | 0000 0000 0000 0000 0000 0000 0000 0001 |
-1 | 1000 0000 0000 0000 0000 0000 0000 0001 |
相加 | 1000 0000 0000 0000 0000 0000 0000 0010 |
结果为-2,所以科学家们想到用补码计算,
数字 | 补码 |
---|---|
1 | 0000 0000 0000 0000 0000 0000 0000 0001 |
-1 | 1111 1111 1111 1111 1111 1111 1111 1111 |
相加 | 1 0000 0000 0000 0000 0000 0000 0000 0000 |
将最高位的1截断,只保留后32位有效位,算出的结果就为0。
大小端字节顺序
- 大端:指数据的低位,保存在内存的高地址处,而高位,保存在内存的低地址处。
- 小端:指数据的低位,保存在内存的低地址处,而高位,保存在内存的高地址处。
如int a = 10;
十六进制为 0x 00 00 00 0a ,0a是数据的低位,如果0a在高地址处,就是大端字节顺序。如果0a在低地址处,就是小端字节顺序。
signed & unsigned
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d b=%d c=%d",a,b,c);
return 0;
}
-1的补码是1111 1111 1111 1111 1111 1111 1111 1111
char是一个字节(byte),也就是8个bit位,因此截断,所以a,b,c存储的补码是1111 1111。
当a,b,c以 %d 的形式打印时,要发生整型提升。
在vs环境中,char == signed char 。
有符号时(signed),补符号位,所以a 补齐时是 1111 1111 1111 1111 1111 1111 1111 1111 (补码)。
无符号时(unsigned), 补0,所以c补齐是0000 0000 0000 0000 0000 0000 1111 1111(补码)。
打印的是原码,因为正数的原码、反码、补码相同,所以结果为255。
浮点数在内存中的存储
根据国际标准IEEE(电气和电子工程协会)754规定,任何一个二进制浮点数 V 可以表示下面这种形式:
- (-1)S * M * 2E
- (-1)S 表示符号位,当S = 0, V 为正数,S = 1,V为负数。
- M 表示有效数字,大于等于1,小于2.
- 2E 表示指数位。
例如:十进制数5.5,转为二进制为101.1
以上述形式书写应为 -10 * 1.011 * 2 2
所以S=0,M=1.011 ,E = 2 。
IEEE754规定,对于32位浮点数(float),最高的一位是符号位S,接着8位是指数E,剩下的23位为有效数字M
对于64位浮点数(double),最高的一位是符号位S,接着的11位是指数E,剩下的52位为有效数字
IEEE754对M和E,还有特别规定。
- 1 <= M <= 2 , 也就是说,M可以写成1.XXXXXXXXX的形式,其中XXXXXXXX表示小数部分。所以,规定在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面XXXXXXX部分。
- 规定存入E的真实值时必须在加上一个中间数,对于8位的E,这个中间值为127,11位的E,中间值为1023。
-
- E不全为0或不全为1时,指数E的计算值(真实值+中间值)减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
-
- E全为0时,E等于1-127(或1-1023),即为真实值
-
- E全为1时,E表示±无穷大(正负取决于符号位S)