您的位置:首页 > 其它

结构体对齐——结构体内存布局

2013-07-26 10:47 239 查看
在C语言中,可以通过#pragma pack(n)来指定结构体按n字节对齐(这里的n是2的较小整数次幂)。如果程序设计者不指定对齐字节数,那么默认的会按照结构体中最长那一项对齐,如在64位操作系统中,当结构体中出现(void *),(long)类型,则必然是按照8字节对齐;当最大的是int,那么就按照4字节对齐;对于数组,如结构体中有int数组int
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。

当然,也可以画出对应的内存布局图,按照最长的那个对齐也能很明显的看出结果来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: