目录
偏移数:类似于数组的下标,指的是结构体每个成员的首个地址距离结构体起始位置的距离。

举例:
- struct S1
- {
- char c1;
- int i;
- char c2;
- };
-
- int main()
- {
-
- printf("%d\n",sizeof(struct S1));
- return 0;
-
- }
以上代码是寻求一个结构体在内存中所占的字节大小。
按照平常的逻辑理论,这里的结构体大小理论上说,应该是六个字节,因为成员c1占一个字节,成员i占四个字节,成员c2占一个字节,所以加在一起一共是6个字节。
但答案真是如此吗?

结果算出的是12个字节。
而后,我又将结构体的成员顺序进行调换,结果还会是12个字节吗?
- struct S1
- {
- char c1;
- char c2;
- int i;
- };
-
- int main()
- {
-
- printf("%d\n",sizeof(struct S1));
- return 0;
-
- }
通过运算,我们得知,最后得到的是八个字节。
是不是很奇怪,明明成员内容都是一样的,只不过调换了顺序,最后结构体的字节大小却发生了改变,这是为什么?
其实这是和结构体的内存对齐有关!

概念:
结构体的对齐本质上就是求结构体的大小。
1. 结构体的第⼀个成员对⻬到相对结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩(变量的字节大小)的较⼩值。
VS中默认的值为8
Linux中没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的 整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
- struct S1
- {
- char c1;
- int i;
- char c2;
- };


- struct S1
- {
- char c1;
- char c2;
- int i;
- };
上述代码也是如此:


在掌握普通结构体的所占内存和对齐后,那么关于结构体嵌套的对齐值和内存该如何计算呢?
- struct S3
- {
- double d;
- char c;
- int i;
- };
-
- struct S4
- {
- char c1;
- struct S3 s3;
- double d;
- };
- printf("%d\n", sizeof(struct S4));
先求第一个struct S3的所占内存:
再求struct S4所占的内存:


- struct S
- {
- char c;
- int i;
- };

假设以上是一段内存,前面一段是不用内存对齐的模式,后面一段是使用内存对齐的模式。
二者看似毫无关系,且我们还觉得第二个模式还会浪费内存。
但是,内存对齐其实是一种那空间换取时间的操作。
为什么呢?这其实是和编译器的读取有关,vs编译器是32位机器,所以读取字节是一次读四个,而后要当你的结构体第一个成员是char第二个成员是int 时,且不进行对齐那么要读两次内存。
甚至不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定 类型的数据,否则抛出硬件异常。

- #include
- #pragma pack(8)//设置默认对齐数为8
- struct s1
- {
- char c1;
- int i;
- char c2;
- };
- #pragma pack()//取消设置的默认对齐数,还原为默认
