C语言数据在内存中的存储(后续会持续优化)

在 C 语言编程中,数据在内存里到底怎么存是核心底层知识点,它直接决定了代码的运行结果、数据溢出、字节序问题,也是面试高频考点。今天就把整数存储、大小端字节序、浮点数存储一次性讲透。


目录

  1. 前言:为什么要学内存存储
  2. 整数在内存中的存储
  3. 大小端字节序与判断
  4. 经典整型内存练习题解析
  5. 浮点数在内存中的存储(IEEE 754)
  6. 浮点数经典面试题详解
  7. 全文总结
  8. 面试高频考点速记

1. 前言:为什么要学内存存储

C 语言是贴近硬件的语言,数据溢出、符号扩展、字节序、指针越界、类型强转等问题,本质都来自内存存储规则。搞懂这一章,你才能真正看懂底层、写稳代码、过面试。


2. 整数在内存中的存储

2.1 原码、反码、补码

整数的二进制表示有三种:原码、反码、补码 。有符号整数最高位是符号位:0 表示正数,1 表示负数

  • 正整数:原码 = 反码 = 补码
  • 负整数:
    • 原码:直接翻译二进制
    • 反码:符号位不变,其余按位取反
    • 补码:反码 + 1

2.2 整数为什么存补码

C 语言中,整数在内存只存补码,原因:

  1. 统一处理符号位与数值位
  2. CPU 只有加法器,补码让加减法统一实现
  3. 补码与原码互转不需要额外硬件电路

3. 大小端字节序与判断

3.1 什么是大小端

超过 1 字节的数据,存储时有字节顺序:

  • 大端:高位字节存低地址,低位字节存高地址
  • 小端:低位字节存低地址,高位字节存高地址

示例:int a = 0x11223344

  • 大端:11 22 33 44
  • 小端:44 33 22 11(X86 默认小端)

3.2 为什么有大小端

计算机以字节为单位寻址,而处理器寄存器宽度大于 1 字节,多字节数据必须规定排放顺序,因此出现大小端。

3.3 代码判断机器字节序

c

运行

复制代码
// 方法1:指针强转解引用
int check_sys() {
    int i = 1;
    return *(char *)&i;
}

// 方法2:共用体(union)
int check_sys() {
    union {
        int i;
        char c;
    }un;
    un.i = 1;
    return un.c;
}

int main() {
    int ret = check_sys();
    if(ret == 1)
        printf("小端\n");
    else
        printf("大端\n");
    return 0;
}

返回 1 → 小端;返回 0 → 大端。


4. 经典整型内存练习题解析

4.1 char 正负值打印

c

运行

复制代码
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("%d,%d,%d",a,b,c); 
// 输出:-1,-1,255

4.2 char 越界问题

c

运行

复制代码
char a = -128;
printf("%u\n",a); 
// 输出:4294967168

4.3 无符号死循环陷阱

复制代码
unsigned char i = 0;
for(i=0; i<=255; i++){
    printf("hello world\n");
}
// 无限循环

4.4 数组指针 + 字节序综合题

复制代码
// X86小端环境
int a[4] = {1,2,3,4};
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
// 输出:4,2000000

5. 浮点数在内存中的存储(IEEE 754)

5.1 存储标准公式

任意二进制浮点数:V = (-1)^S * M * 2^E

  • S:符号位(0 正 1 负)
  • M:有效数字(1≤M<2)
  • E:指数位

5.2 float /double 存储布局

  • float(32 位):1 位 S + 8 位 E + 23 位 M
  • double(64 位):1 位 S + 11 位 E + 52 位 M

5.3 存储规则

  1. M 省略首位 1:只存小数部分,提升精度
  2. E 加偏移量:float+127,double+1023,兼容负数指数

5.4 读取时 E 的三种情况

  1. E 不全 0 不全 1:常规解析,E-127 得真实值
  2. E 全 0:表示 ±0 或极小数字,E=1-127
  3. E 全 1:M 全 0 表示无穷大,否则为 NaN

6. 浮点数经典面试题详解

复制代码
int n = 9;
float *p = (float *)&n;
printf("%d %f\n", n, *p); 
// 输出:9 0.000000

*p = 9.0;
printf("%d %f\n", n, *p); 
// 输出:1091567616 9.000000

解析:

  • 整数 9 按浮点数解析:E 全 0,结果趋近于 0
  • 浮点数 9.0 按 IEEE 754 存储,转整数解析为 1091567616

7. 全文总结

  1. 整数在内存中以补码存储,统一符号与运算
  2. 多字节数据存在大小端,X86 默认小端
  3. 无符号数溢出、char 越界、符号扩展是常见坑
  4. 浮点数严格遵循IEEE 754,按 S/E/M 分段存储
  5. 整型与浮点强转,内存不变、解析规则不同

8. 面试高频考点速记

  1. 整数为什么存补码?
  2. 大小端概念 + 手写判断代码
  3. char 越界、无符号死循环原因
  4. IEEE 754 浮点数存储结构
  5. int 与 float 互转面试题原理
相关推荐
不正经学生3 小时前
C语言预处理详解:编译器真正动手之前的那些事
c语言·开发语言·算法·面试·bug
门思科技3 小时前
LoRaWAN 设备类别:Class A、B、C 对比与选型指南
c语言·开发语言·php
xiaobobo33307 小时前
c语言中for循环条件中定义临时栈变量的作用域
c语言·for循环条件定义栈变量·大括号作用域·独立栈变量
惜离殇8 小时前
从零开始的敲代码生活--Linux应用软件(文件操作基础1)
linux·c语言·文件操作·标准io
潘潘的嵌入式日记9 小时前
I²C 从机接收总被覆盖?双缓冲要在 STOP 时交接
c语言·开发语言·单片机
xx~t11 小时前
嵌入式——Linux软件编程——网络1
linux·c语言·网络·vscode·网络协议
羚尔14 小时前
C语言数组
c语言·开发语言
老当益壮梁奶奶17 小时前
Linux软件编程学习笔记(十一):深入浅出 TCP 协议与 Socket 编程实践
linux·c语言·笔记·学习·tcp/ip
Navigator_Z18 小时前
LeetCode //C - 1223. Dice Roll Simulation
c语言·算法·leetcode
Patrick在香港19 小时前
Python 拉取 C&SD 官方 API:香港 2022 年已跨过“超老龄线“,而抚养比正在爬回 1961
android·c语言·python·数据分析·时序数据库·数据可视化·香港