#include <stdio.h>
#pragma pack(8)
struct example1
{
short a;
long b;
};
struct example2
{
char c;
example1 struct1;
short e;
};
int main(void)
{
example2 struct2;
printf("%u\n", sizeof(example1));
printf("%u\n", sizeof(example2));
printf("%u\n", (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2));
return 0;
}
今天需要仔细的总结一下内存对齐机制了,参考了http://www.cnblogs.com/clover-toeic/p/3853132.html的博文。
首先需要牢记对其准则:
①数据类型自身的对齐值,例如char自身对齐值为1字节,int为4字节
②结构体或类的自身对齐值,其成员中自身对齐值最大的那个值
③制定对齐值,#pragma pack(value)时制定对齐值
④数据成员,结构体和类的有效对齐值,为其中自身对齐值和指定对齐值中较小者,即有效对齐值。
其中,有效对齐值N是最终用来决定数据存放地址方式的值。有效对齐N表示“对齐在N上”,即该数据的“存放起始地址%N=0”。而数据结构中的数据变量都是按定义的先后顺序存放。第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐存放,结构体本身也要根据自身的有效对齐值圆整(即结构体成员变量占用总长度为结构体有效对齐值的整数倍)。
字节数规定:
①sizeof(short int)<=sizeof(int)
②sizeof(int)<=sizeof(long int)
③short int至少应为16位(2字节)
④long int至少应为32位。
由此开始分析这个题目的解答:
从#include看起,包含了stdio.h头文件。同时用预处理命令使③制定的自身对齐值为8,
从main函数开始分析,首先声明了一个example2结构体,然后打印example1,example2结构体的占用字节空间大小,最后打印example2结构体中,example1结构体的地址减去example2结构体地址的值。
main函数很简单,然后来看example1结构体。结构体包含short和long,由于32位机器short2字节,long4字节,所以结构体最大自身对齐值为4,此时内存分配为short 2,填充 2,long 4,总共占用8字节。
example2结构体中example1结构体最大对齐值为4,char为1,short为2,预处理定义为8,所以还是按照4字节对齐,此时内存分配为char 1,填充 3,example1 8,short 2,填充 2,总共占用16字节。
由于创建的堆栈是在堆上分配的,堆地址是递增的,假设example2的初始地址为x,然后char和填充字节占了4字节,然后就是example1结构体了,so,(unsigned int)(&struct2.struct1) - (unsigned int)(&struct2)为(x+4)-x = 4。
本次验证采用了visual studio,本机电脑为linux,等到周三考完试把visual studio 截图拷上去
deepin 15.3 64验证结果如下: