前言: 本期开始详解结构体,由于文章过长,所以分了几篇文 包括结构体概念,结构体的内存对齐以及位段 若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持 谢谢大家 ! ! !
先来看看一段代码: (判断结构体所占字节数)
#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 的成员一致,但为什么大小却不一样呢? 难道说结构体成员不是简单连续存放? 这就是因为结构体中存在内存对齐现象
规则1:
第一个成员对齐到偏移量为0的地址规则2:其他成员要对齐到"对齐数"的整数倍地址对齐数 =编译器默认对齐数 与 成员变量大小的较小值(VS默认对齐数默认8,Linux gcc无默认值) 规则3:结构体总大小为最大对齐数的整数倍规则4:嵌套结构体按自身最大对齐数对齐
这样讲你肯定听不懂,下面我们带入例题和图解吧: s1图解:

s2图解:

有了这两张图 想必大家已经知道了为什么例题的答案是 8 和 12 了吧
但是 为什么要有内存对齐呢? 这样不是更加消耗空间吗?
1.硬件限制: 并非所有硬件平台都能访问任意地址上的任意类型数据,某些平台只能在特定地址处访问特定类型数据。 2.访问异常: 若违反硬件规定(如在非4的倍数地址访问整型数据),会抛出硬件异常。 3.强制对齐: 例如某些硬件要求整型数据必须在地址为4的倍数处访问,因此存储时必须对齐到4的倍数。
访问次数的差异: 对齐内存:处理器只需1次内存访问即可读取完整数据 未对齐内存:可能需要2次内存访问才能拼凑出完整数据
相当于用空间换时间,通过牺牲部分内存空间(填充空白字节)来提升内存访问效率
我们已知,VS默认对齐数默认8,Linux gcc无默认值 但是,我们可以通过代码来自行修改默认对齐数 如下:
#prama pack( x );x就为想要更改的默认对齐数 但一般都是2的次方数数(1,2,4,8)
位段 为一种数据结构,是结构体的一种特殊形式 可以指定成员占用的二进制位数,把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作 成员类型通常为整型(int/unsigned int)或字符型(char) 例如: 成员名后跟冒号和位数,如 int a : 2 ; 表明指定变量 a 的存储只给 2 个bit位(原本32bit位)
下面给出一个例题,大家也可以猜猜结果是多少
代码演示:
#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个字节吗? 这就是位段的作用了 位段可以把数据以位的形式紧凑的储存
注意:位段涉及很多不确定性因素,是不跨平台的(每一个编译器不一样)须小心使用,这里我们以 VS 为例
位段的内存分配总共有几个步骤: 1.空间按需以4字节(int)或1字节(char)为单位开辟空间 2.给定空间后,VS在空间内部从右向左使用 3.当空间不足时,VS会开辟新空间,以此循环
文字解释不清,这里还是用图解吧:

如上图,这就是位段在内存中如何内存分配
使用位段时要注意很多:
本期资料来自于:
OK,本期的结构体详解到这里就结束了 由于文章过长,所以分了几篇文 若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持 本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!! 新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!! 支持一下(三连必回QwQ)