1.什么是结构体字节对齐?
(1)先看一个例子
struct ab{
char a;
int b;
}
struct ab buf;
printf("the buf is %d\n",sizeof(buf));
显而易见,我们想看看这个结构体占了几个字节,理论上,char占1字节,int占4字节,总的是占了5字节,但是请看输出结果:
the buf is 8
其实这是系统给char和int各自都分配了4个字节,对于一个32位系统来说,就意味着有32位总线,为了提高效率呢,系统希望32位总线同时访问内存,那么能同时访问的最大内存是多少呢,那就是2的32次方=4字节。
所以对于上述结构体,5个字节,如果系统每次访问4个字节,无论如何也要访问两次,但是如果按照常规方法,得到的是这样的数据空间【char】【int】【int】【int】、【int】,最终int被拆散了,到时候还要重组,很麻烦。于是我们这样定义【char】【】【】【】、【int】【int】【int】【int】,同样是访问两次,而我们不再需要拆分变量。(“【】”代表一个字节空间)所以我们宁愿多分配空间给变量。字节对齐的本质就出来了:以空间换取时间。
(2)再看一个例子
struct abc{
char a;//1个字节
short b;//2个
int c;//4个
}
struct abc buf;
printf("the buf is %d\n",sizeof(buf));
这样我们是不是可以认为打印结果应该是12? 3×4嘛!自信地打印一下:
the buf is 8
卧槽?怎么还是8???
因为系统没有这么死板,系统一看第一个变量空出来的字节空间足够存放下一个,它就机智地这样定义内存了【char】【】【short】【short】、【int】【int】【int】【int】。所以怎么判断字节是怎么对齐的呢,要看当前变量富余的空间够不够存放下一个变量。
2.结构体字节对齐的方法
(1)在c语言中
#include <stdio.h>
//默认情况下,结构体一般在内存中的自动对齐格式是4个字节 ,即向四个字节的变量对齐
//设置手动对齐
//如果这里是4,那么下面的打印就是8
//如果这里是2,那么下面的打印就是6
//如果这里是1,那么下面的打印就是5
#pragma pack(4)
struct mystu
{
char a ;
int b ;
};
#pragma pack()
int main(void)
{
printf("str:%d\n",sizeof(struct mystu));
return 0 ;
}
(2)另外,在linux系统中,GCC推荐的对齐指令如下:
方法一:attribute((packed))
#include <stdio.h>
struct mystu
{
char a ;
int b ;
}_attribute_((packed));
方法二:attribute((aligned(n)))
#include <stdio.h>
struct mystu
{
char a ;
int b ;
}_attribute_((aligned(4)));