首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C语言】struct结构体内存对齐和位段(超详解)

【C语言】struct结构体内存对齐和位段(超详解)

作者头像
zore
发布2025-12-30 18:50:24
发布2025-12-30 18:50:24
2120
举报
文章被收录于专栏:C/C++ 专栏C/C++ 专栏

前言: 本期开始详解结构体,由于文章过长,所以分了几篇文 包括结构体概念,结构体的内存对齐以及位段 若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持 谢谢大家 ! ! !

二、结构体的内存对齐

1.现象观察

先来看看一段代码: (判断结构体所占字节数)

代码语言:javascript
复制
#include <stdio.h>

struct s1
{
	char name;
	char number;
	int age;
}; 

struct s2
{
	char name;
	int age;
	char number;
};

int main()
{
	int sz1 = sizeof(struct s1);
	int sz2 = sizeof(struct s2);

	printf("s1=%d\n\ns2=%d\n\n", sz1, sz2);
	
	return 0;
}

大家可以猜猜 s1 和 s2 这两个结构体占多少字节 运行结果:

在这里插入图片描述
在这里插入图片描述

我们可以看到,虽然 s1 和 s2 的成员一致,但为什么大小却不一样呢? 难道说结构体成员不是简单连续存放? 这就是因为结构体中存在内存对齐现象

2.对齐规则

规则1第一个成员对齐到偏移量为0的地址 规则2其他成员要对齐到"对齐数"的整数倍地址 对齐数 = 编译器默认对齐数 与 成员变量大小的较小值 (VS默认对齐数默认8,Linux gcc无默认值) 规则3结构体总大小为最大对齐数的整数倍 规则4嵌套结构体按自身最大对齐数对齐

这样讲你肯定听不懂,下面我们带入例题和图解吧: s1图解:

在这里插入图片描述
在这里插入图片描述

s2图解:

在这里插入图片描述
在这里插入图片描述

有了这两张图 想必大家已经知道了为什么例题的答案是 8 和 12 了吧

但是 为什么要有内存对齐呢? 这样不是更加消耗空间吗?

3.为什么存在内存对齐

  • 平台原因

1.硬件限制: 并非所有硬件平台都能访问任意地址上的任意类型数据,某些平台只能在特定地址处访问特定类型数据。 2.访问异常: 若违反硬件规定(如在非4的倍数地址访问整型数据),会抛出硬件异常。 3.强制对齐: 例如某些硬件要求整型数据必须在地址为4的倍数处访问,因此存储时必须对齐到4的倍数。

  • 性能原因

访问次数的差异对齐内存:处理器只需1次内存访问即可读取完整数据 未对齐内存:可能需要2次内存访问才能拼凑出完整数据

相当于用空间换时间,通过牺牲部分内存空间(填充空白字节)来提升内存访问效率

4.修改默认对齐数

我们已知,VS默认对齐数默认8,Linux gcc无默认值 但是,我们可以通过代码来自行修改默认对齐数 如下: #prama pack( x ); x就为想要更改的默认对齐数 但一般都是2的次方数数(1,2,4,8)

三、结构体实现位段(以VS为例)

1.什么是位段

位段 为一种数据结构,是结构体的一种特殊形式 可以指定成员占用的二进制位数,把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作 成员类型通常为整型(int/unsigned int)或字符型(char) 例如: 成员名后跟冒号和位数,如 int a : 2 ; 表明指定变量 a 的存储只给 2 个bit位(原本32bit位)

2.例题

下面给出一个例题,大家也可以猜猜结果是多少

代码演示:

代码语言:javascript
复制
#include <stdio.h>

struct S1
{
	int a : 2;
	int b : 5;
	int c : 10;
	int d : 30;
}; 

int main()
{
	int sz = sizeof(struct S1);

	printf("S1=%d\n\n", sz);
	
	return 0;
}

运行结果:

在这里插入图片描述
在这里插入图片描述

是不是很奇怪,为什么结果是8,这个结构体不应该占16个字节吗? 这就是位段的作用了 位段可以把数据以位的形式紧凑的储存

3.位段的内存分配

注意:位段涉及很多不确定性因素,是不跨平台的(每一个编译器不一样)须小心使用,这里我们以 VS 为例

位段的内存分配总共有几个步骤: 1.空间按需以4字节(int)或1字节(char)为单位开辟空间 2.给定空间后,VS在空间内部从右向左使用 3.当空间不足时,VS会开辟新空间,以此循环

文字解释不清,这里还是用图解吧:

在这里插入图片描述
在这里插入图片描述

如上图,这就是位段在内存中如何内存分配

4.位段的注意事项

使用位段时要注意很多:

  1. 位段涉及很多不确定性因素,是不跨平台的(每一个编译器不一样)
  2. 位段中存在多个成员共用一个字节的情况,这样成员的起始位置就不是字节的起始位置 故这些成员无地址,不能使用&、scanf 只能输入到一变量中后再赋值

结语

本期资料来自于:

https://legacy.cplusplus.com/

OK,本期的结构体详解到这里就结束了 由于文章过长,所以分了几篇文 若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持 本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!! 新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!! 支持一下(三连必回QwQ)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二、结构体的内存对齐
    • 1.现象观察
    • 2.对齐规则
    • 3.为什么存在内存对齐
    • 4.修改默认对齐数
  • 三、结构体实现位段(以VS为例)
    • 1.什么是位段
    • 2.例题
    • 3.位段的内存分配
    • 4.位段的注意事项
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档