结构体对齐——结构体内存布局
2013-07-26 10:47
239 查看
在C语言中,可以通过#pragma pack(n)来指定结构体按n字节对齐(这里的n是2的较小整数次幂)。如果程序设计者不指定对齐字节数,那么默认的会按照结构体中最长那一项对齐,如在64位操作系统中,当结构体中出现(void *),(long)类型,则必然是按照8字节对齐;当最大的是int,那么就按照4字节对齐;对于数组,如结构体中有int数组int
a[20],也是4字节对齐的,只跟数据类型有关。
这里,看一下如下代码以及运行结果
对这里的结果进行分析,不论是在堆还是栈中,内存布局形式是一样的,如下图
可以看出,由于long类型p的存在,数据结构按照8字节对齐,其中白色部分为未使用部分,如果调整一下数据结构存放的位置,如把c1放在ch后面,那么可以节约8字节的空间。
给定一个数据结构,如果是默认对齐方式,如何判断所占字节数呢?这里有一个比较简单但又拗口的方法,以博客中的数据结构为例,将结构体test分成三部分ABC,其中A为p前面的变量构成的虚拟结构体,B为long类型变量p,C为p后面的变量构成的虚拟结构体,那么sizeof(struct test) = sizeof(A)按8字节对齐
+ sizeof(B) + sizeof(C)按8字节对齐。sizeof(C)的计算方式同sizeof(struct test)是相同的,也就是说这里是一个递归的方式计算,递归结束的条件是虚拟结构体中只有一个变量。计算sizeof(A)时,其结果为4;计算sizeof(C)时,就以int进行分割,得到sizeof(C)的值为(1按4字节对齐 + 4 + 1按四字节对齐),即12;最终算的sizeof(struct test) = 32。
当然,也可以画出对应的内存布局图,按照最长的那个对齐也能很明显的看出结果来。
a[20],也是4字节对齐的,只跟数据类型有关。
这里,看一下如下代码以及运行结果
#include<stdio.h> #include<stdlib.h> //#pragma pack(2)//注释掉这一行,按照默认的对齐方式 struct test { int n1; long p; char ch; int n2; char c1; }; void print(struct test *p) { printf("&p->n1 : %p\n",&p->n1); printf("&p->p : %p\n",&p->p); printf("&p->ch : %p\n",&p->ch); printf("&p->n2 : %p\n",&p->n2); printf("&p->c1 : %p\n",&p->c1); } int main() { struct test t; struct test *p = &t; printf("sizeof(test) = %d\n",sizeof(struct test));//输出结构体大小 printf("In stack:\n");//看在栈上的地址 print(p); p = (struct test *)malloc(sizeof(struct test)); printf("In heap:\n");//看在堆上面的地址 print(p); free(p); return 1; }运行结果如下
对这里的结果进行分析,不论是在堆还是栈中,内存布局形式是一样的,如下图
可以看出,由于long类型p的存在,数据结构按照8字节对齐,其中白色部分为未使用部分,如果调整一下数据结构存放的位置,如把c1放在ch后面,那么可以节约8字节的空间。
给定一个数据结构,如果是默认对齐方式,如何判断所占字节数呢?这里有一个比较简单但又拗口的方法,以博客中的数据结构为例,将结构体test分成三部分ABC,其中A为p前面的变量构成的虚拟结构体,B为long类型变量p,C为p后面的变量构成的虚拟结构体,那么sizeof(struct test) = sizeof(A)按8字节对齐
+ sizeof(B) + sizeof(C)按8字节对齐。sizeof(C)的计算方式同sizeof(struct test)是相同的,也就是说这里是一个递归的方式计算,递归结束的条件是虚拟结构体中只有一个变量。计算sizeof(A)时,其结果为4;计算sizeof(C)时,就以int进行分割,得到sizeof(C)的值为(1按4字节对齐 + 4 + 1按四字节对齐),即12;最终算的sizeof(struct test) = 32。
当然,也可以画出对应的内存布局图,按照最长的那个对齐也能很明显的看出结果来。
相关文章推荐
- NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构
- c#编程指南(十二) 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局
- 《coredump问题原理探究》Linux x86版5.8节C风格数据结构内存布局之结构体数组结构体coredump
- C语言结构体在内存中的布局(直接对齐)
- 结构体的内存对齐方式(结构体大小计算 sizeof)(
- 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局
- sizeof(结构体)和内存对齐
- 内存对齐.结构体对齐
- 结构体的内存对齐问题
- 结构体内存对齐
- 内存字节对齐---对结构体非常重要。不能用memcpy简单的移动指针进行赋值
- Arm结构体gcc内存边界对齐问题(zt)
- 结构体和联合体的大小,结构体内存对齐的原因、规则以及柔性数组
- 关于结构体的内存对齐
- 《coredump问题原理探究》Linux x86版5.6节C风格数据结构内存布局之复合类型构成的结构体
- 学习笔记-C/C++-结构体与sizeof,内存对齐的题目怎么做
- C语言结构struct的内存对齐
- C语言结构体中内存对齐问题
- 结构体内存分配对齐策略
- <C语言>结构体与联合体(共用体)的地址排布问题(内存字节对齐)