目录
1、整数在内存中的存储
首先了解整数的二进制表示方法有三种:原码、反码、补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位最高位的⼀位是被当做符号位,剩余的都是数值位。
注:有符号整型的第一位为符号位,无符号整型的第一位仍然是数值位,所以无符号整型的内存是有符号整型内存的2倍。
2、大小端字节序和字节序判断
当我们了解了整数在内存中存储后,我们调试看⼀个细节:
//0x十六进制,一个16进制位是4个二进制位,两个16进制位是8个2进制位,即1个字节。
#include <stdio.h>
int main()
{
int a = 10; //0x 00 00 00 0a
int b = 0x11223344;
return 0;
}
调试后可以发现a、b中的数字是按照字节为单位,倒着存储的:
2.1 什么是大小端
2.2 为什么有大小端
2.3 判断大小端字节序
请简述大端字节序和小端字节序的概念,设计⼀个小程序来判断当前机器的字节序。-百度笔试题
可以通过 int 型变量数字 1 的存储地址来判断,如果对首地址解引用是0则是大段存储,如果是1则是小端存储。
2.4 练习题
①分析下面代码:
那为什么不同类型打印的结果不同呢?
printf("a=%d,b=%d,c=%d", a, b, c);
由于最后以 %d 的形式输出,而 %d 以十进制的形式打印有符号的整数。以打印 a 、b 为例,(vs默认char a 就是有符号char,故 a 和 b 原理相同)首先需要进行整型提升,对于char a来说,a - 11111111,(因为int类型占四个字节,char类型占一个字节)其中最高位就是符号位。所以整型提升(整型提升的解释在下面)后高位补的都是1,即:
a 的补码: 11111111 11111111 11111111 11111111
%d 以十进制的形式打印有符号整数,整型提升后的第一位为符号位(1:负数 ,0:正数),a的补码第一位为1,说明为负数。由于存放内存的为补码,需要计算其原码,即:负数的原码 = 补码取反 + 1。那么打印出的a原码为:
a - 10000000 00000000 00000000 00000001
因此,最终打印出来的 a、b 均为 -1。而因为 c 是无符号类型,在整型提升的时候高位均补的0:
c 的补码:00000000 00000000 00000000 11111111
同时在打印时以 %d 形式输出,仍认为 c 是有符号数,即高位符号位是 0,表示正数。正数的原码、反码、补码相同,所以输出结果为 255 。
什么是整型提升?
②分析下面代码:
3、浮点数在内存中的存储
通过上述例子可以发现,虽然 float 和 int 类型都占四个字节。但是以整型数据存储,再以浮点数类型拿出或者以浮点数类型存储,再以整型数据拿出都是不可以的。由此可以发现,整型数据和浮点型数据在内存中的存储是完全不同的。
3.1 十进制浮点数转换为二进制数
将带有小数部分的十进制浮点数转换为二进制数的原理可以通过以下步骤来说明:
-
整数部分转换:首先将十进制数的整数部分转换为二进制数,方法与整数转换相同。
-
小数部分转换:将十进制数的小数部分转换为二进制数,使用乘2取整法(乘法部分向左移动,取整部分作为二进制位)。
-
合并整数和小数部分:将得到的整数部分和小数部分合并,中间加上小数点,即可得到完整的二进制表示。
举例说明,将十进制浮点数 6.25 转换为二进制数:
整数部分 6 转换为二进制数为 110。 小数部分 0.25 转换为二进制数,使用乘2取整法:
- 0.25 * 2 = 0.5,整数部分为 0。
- 0.5 * 2 = 1.0,整数部分为 1。 因此,0.25 转换为二进制数为 0.01。
将整数部分 110 和小数部分 0.01 合并,中间加上小数点,得到二进制表示为 110.01。
因此,十进制浮点数 6.25 转换为二进制数后为 110.01。
3.2 浮点数的存储
3.3 浮点数存的过程
例:还是以十进制的 6.25 为例,根据二进制浮点数表示公式:
6.25 可以表示为:
那么对应的 S = 0 ,M = 1.1001,E = 2;
因此第一个比特位存储 0 ,由于 E=2 且为 8 位即 2 + 127 = 129,写成二进制为10000001, M 有 23 位所以在 1001 后面要进行补零,最终 6.25 在 32 比特位上面存储形式为:01000000110010000000000000000000,将其转换为16进制得 40c80000,如下所示:
3.4 浮点数取的过程
3.5 练习题
再次对上述代码进行分析,为什么以浮点数形式输出整数 9 的结果为0.000000。9以整型的形式存储在内存中,得到如下⼆进制序列:0000 0000 0000 0000 0000 0000 0000 1001