C语言——结构体的内存存储规则

一、引言

cpp 复制代码
struct stu1
{
	char a;
	short b;
	int c;
};
struct stu2
{
	char a;
	int c;
	short b;
};

int main()
{
	//输出结构体所占字节大小
	printf("%d\n", sizeof(struct stu1));  // 结果:8
	printf("%d\n", sizeof(struct stu2));  // 结果:12
}

在 C 语言中定义结构体时,成员变量顺序不同,最终结构体占用的内存大小也不同 ,并非简单把所有成员字节数相加。这背后就是结构体内存对齐机制。

二、内存对齐核心思想

(一)为什么要内存对齐

计算机CPU访问内存数据时,不会零散逐字节读取,而是优先以2的整数倍字节批量访问,常见为2Byte、4Byte、8Byte,以此提升读写效率。

内存对齐是为了让每一个成员的内存尽可能保持对齐,这样CPU一次访问的字节数,就可以直接完整取到这个元素。

核心思想:用空间换取访问时间效率

(二)内存对齐规则

1.第一个成员在与结构体变量偏移量为0的地址处

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处

(1)对齐数 = 编译器默认对齐数与该成员大小的较小值

(2)VS环境下默认对齐数是8

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍

4.如果是嵌套结构体

(1)嵌套的结构体对齐到自己的最大对齐数的整数倍处

(2)结构体整体大小就是"所有最大对齐数(含嵌套的对齐数)"的整数倍

cpp 复制代码
struct stu1
{
	char a;		// 偏移 0,占用 1 字节 -> 【0】
    			// 偏移 1,"浪费 1 字节"(为了对齐)
	short b;	// 对齐数:min(2, 8) = 2
    			// 从偏移 2 开始,占用 2 字节 -> 【2, 3】
	int c;		// 对齐数:min(4, 8) = 4
    			// 从偏移 4 开始,占用 4 字节 -> 【4, 5, 6, 7】
};	

// 总大小:8 Byte
// 校验:8 % 最大对齐数(4) == 0,满足规则!
cpp 复制代码
struct stu2
{
	char a; 	// 偏移 0,占用1字节   【0】
         		// 偏移 1、2、3,浪费3字节(对齐填充)
	int c;		// 对齐数:min(4, 8) = 4
         		// 偏移 4 开始,占用4字节 【4,5,6,7】
	short b;	// 对齐数:min(2, 8) = 2
         		// 偏移 8 开始,占用2字节 【8,9】
};	

// 当前总长度:10 Byte
// 校验:10 % 最大对齐数(4) != 0,不满足规则!
// 自动填充字节,补齐到 12 Byte

(三)手动修改默认对齐数

cpp 复制代码
#pragma pack(n)    // 设置默认对齐数为 n(n 只能是 1、2、4、8、16)
#pragma pack()     // 取消手动设置,恢复编译器默认(VS 默认 8)
相关推荐
LDR00611 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术11 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园11 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob11 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
源分享11 天前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm
Luminous.11 天前
C语言--day30
c语言·开发语言
玖玥拾11 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
何以解忧,唯有..11 天前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
謓泽11 天前
C语言不是语法,是通往机器的地图。
c语言·开发语言
云水一下11 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php