整数和浮点数在内存中的存储
一、前言在C语言编程中我们经常使用整数和浮点数但很少有人真正了解它们在内存中是如何存储的。理解这些底层细节能帮助我们写出更健壮的代码也能更好地理解一些“奇怪”的现象比如为什么浮点数运算会有精度问题。本文将深入探讨整数和浮点数在内存中的存储方式。二、整数的存储1. 原码、反码、补码整数在内存中以补码形式存储。要理解补码首先要知道原码和反码。类型 正数 负数原码 符号位为0其余为数值位 符号位为1其余为数值位反码 同原码 符号位不变数值位按位取反补码 同原码 反码1示例 以8位二进制为例1和-1的表示text1 原码0000 00011 反码0000 00011 补码0000 0001-1 原码1000 0001-1 反码1111 1110-1 补码1111 11112. 为什么使用补码使用补码的好处是可以将减法统一为加法运算。CPU只需要设计加法器就能完成加法和减法。例如1 (-1) 0text0000 0001 (1的补码) 1111 1111 (-1的补码) 0000 0000 (0进位丢弃)3. 有符号和无符号有符号整数最高位为符号位0正1负取值范围 -2^(n-1) ~ 2^(n-1)-1无符号整数全部位都是数值位取值范围 0 ~ 2^n - 1类型 字节数 取值范围char 1 -128 ~ 127unsigned char 1 0 ~ 255int 4 -2^31 ~ 2^31-1unsigned int 4 0 ~ 2^32-1三、浮点数的存储1. IEEE 754 标准浮点数遵循 IEEE 754 标准分为三部分存储text浮点数 (-1)^S × M × 2^ESSign符号位0表示正数1表示负数EExponent指数位存储时加上偏移量MMantissa尾数位存储小数点后的有效数字2. float 类型32位text| 1位符号位S | 8位指数位E | 23位尾数位M |偏移量127实际指数 E - 1273. double 类型64位text| 1位符号位S | 11位指数位E | 52位尾数位M |偏移量1023实际指数 E - 10234. 存储示例以 float f 5.5 为例5.5 转二进制101.1科学计数法1.011 × 2^2符号位 S 0指数 E 2 127 129 1000 0001尾数 M 01100000000000000000000隐藏最高位1最终存储0 10000001 011000000000000000000005. 浮点数的精度问题重要 并非所有浮点数都能精确保存例如 0.1 转换为二进制是无限循环小数text0.1 0.00011001100110011...循环计算机只能截断存储因此 0.1 0.2 ≠ 0.3 是常见现象。6. 特殊值情况 符号位S 指数位E 尾数位M0 0 全0 全0无穷大 0/1 全1 全0NaN 0/1 全1 非0四、整型和浮点型存储对比对比项 整型 浮点型存储标准 补码 IEEE 754表示范围 固定范围 更大范围精度 精确 部分值不精确存储结构 直接存储数值 分为S、E、M三部分五、验证代码示例1. 查看整数的补码表示c#include stdio.hint main() {int a -1;unsigned int *p (unsigned int*)a;printf(%#x\n, *p); // 输出0xffffffffreturn 0;}2. 查看浮点数的十六进制存储c#include stdio.hint main() {float f 5.5;unsigned int *p (unsigned int*)f;printf(%#x\n, *p); // 输出0x40b00000return 0;}3. 浮点数精度问题演示c#include stdio.hint main() {float f 0.1f;double d 0.1;printf(float 0.1 : %.20f\n, f);printf(double 0.1: %.20f\n, d);if (0.1 0.2 0.3) {printf(相等\n);} else {printf(不相等\n);}return 0;}六、常见面试题1. 判断大小端cint check_endian() {int a 1;char *p (char*)a;return *p; // 小端返回1大端返回0}2. 为什么浮点数不能直接判等因为浮点数存储不精确应该用差值比较c#define EPS 1e-6if (fabs(a - b) EPS) {// 认为相等}七、总结整数用补码存储方便统一加减法运算浮点数用 IEEE 754 标准存储由符号位、指数位、尾数位三部分组成浮点数存在精度问题不能精确保存所有小数理解底层存储有助于解决溢出、截断、精度损失等问题八、参考资料IEEE 754 标准文档《深入理解计算机系统》第2章C语言标准C99/C11