在这里只总结结构体的字节对齐问题,看下面的结构体
struct s1
{
char a;
int b;
short c;
};
struct s2
{
char a;
short c;
int b;
};
那么sizeof(s1) = 12, sizeof(s1) = 8;
我们可以假定结构体在内存中的地址是0x0000开始的,那么我们说的字节对齐就是(起始内存地址%自身类型字节) = 0;
所以在这里简单分析下s1是怎么对齐的
a的内存地址是0x0000,自身字节1,它是自然对齐的,
b的自身类型字节是4,如果要对齐,那么起始地址只能是0x0004,范围到0x0007.
c的自身类型字节是2,故起始地址为0x0008,范围到0x0009故不用填充了直接跟在b变量后面,
为什么还要补全两个字节呢,因为假定这是一个结构体数组,那么,下个元素的起始地址是不是也要对齐,所以不管后面有没有变量,都要内存对齐,才不会对后面的变量产生字节不对齐的影响,并且结构体最后补全的字节数取决于变量的最大类型的整数倍,即,在上面是int占四字节,所以结构体的内存必然是4的倍数
当结构体中有char a[0]成员,这样的成员时,这是不会增加结构体内存的,但是a的地址是上面那个成员的地址加一,也就是a后面的成员的地址
补充:对于改变指定字节的方法有几种
一.
#pragma pack (n) //n就是指定的字节
struct ss{
.......
};
#pragma pack () //取消指定字节
二.
struct ss
{
.....
}__attribute__ ((packed)); //指定最小字节对齐,一个字节
三.
struct stu{
....
}__attribute__ ((aligned (1))); //数字为指定一个字节
在这里说一下,这是笔者自己的理解,对于不同平台有不同的规定,像X86平台,字节不对齐只是影响cpu读取内存的速度,但是有些平台必须严格对齐,不然会发送错误。这么说那么就是说cpu也不是按程序员想象那样,int型的就一次去取int型所占有的字节数,而是按照变量存储在内存中什么位置来决定取的次数,接着才是取多少个字节,有不同看法的请指教
补充:如果能分析下面的结构体内存,你就真懂了字节对齐
struct aa
{
char a;
int b;
double c;
};
struct bb
{
char d;
struct
{
int e;
double f;
};
int g;
};
结果是sizeof(aa) = 16; sizeof(bb) = 32
提示:其实结构体套结构体也是一样的都是按最大字节对齐(按结构体中最大的类型对齐,不是类型的叠加),比如上面的struct bb;自己思考吧
下一篇是关于位域在struct中占的内存