【字节对齐】结构体字节对齐的本质和使用

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)));

猜你喜欢

转载自blog.csdn.net/qq_33033059/article/details/90167399