2. 为什么要字节对齐
简单的说来就是为了提高cpu的性能,或者说是为了提高程序运行的效率。当然,在其背后更有简化cpu设计的功效。因此,我们写的c程序为了获得更高的运行效率就必须最大限度的满足cpu对于字节对齐的要求,编译器在其中起着至关重要的作用。
下面的c程序在编译后运行,在终端将会打出”size of type_t is 8”。为什么是8而不是5呢?这是因为编译器考虑到了运行效率,从而将type_t做了4字节对齐的处理。
#include<studio.h>
typedef struct
{
char a;
int b;
}type_t;
int main()
{
printf(“size of type is:%d”,sizeof(type_t));
return 0;
}
这里需要指出的是,编译器会根据具体的结构选择是4字节对齐还是2字节对齐。比如,下面定义的element_t结构,其中sizeof大小应当是4,而不是3,更不会是8。
typedef struct
{
char a;
short b;
}element_t;
下面我们来分析为什么进行字节对齐能提高运行效率。要对数据结构进行更为高效的操作,从cpu的角度就是尽可能减少对内存的访问次数 。对于type_t结构,其内存布局如图1所示,需要指出的是SPARC是big-endian模式,图中b=b0b1b2b3.
在做进一步的分析之前,还需要清除的是,对于32位处理器,其数据总线是32位的。
因此,cpu从内存中存取数据时可以(也只能)一次读入4字节。为此,cpu从内存中存取数据时总是以4字节为边界进行存取的。如果,我们所写的程序只需要访问内存中的一个字节,此时也需要从内存读入4个字节吗?是的。对于一次内存所存取的4个字节中,我们是需要存取其中的一个字节、两个字节或者全部4个字节,cpu如何区分呢?答案是,cpu提供了不同的指令,而由编译器根据情况选择使用不同的指令。
现在,我们开始分析采用字节对齐和不采用字节对齐时,cpu 对于内存的访问次数有何不同。回到图1,先看看采用字节对齐时的情况,从图中可以看出,当cpu需要分别访问a变量和b变量时,无论如何都只需要分别进行一次内存存取,图中的花括号表示一次 内存存取操作。对于不采用字节对齐的情况,a变量无论如何只要进行一次内存操作的,而b变量有可能需要进行二次内存操作,因为这一变量跨越了4字节的边界。这里之所以说是可能,是因为有可能对b进行访问之前,可能刚好完成了对于a的访问,而对a访问时,b0、b1和b2也同时读入(或写入)了,这种情况下,只需要读入(或写入)b3即可。
此外,更为麻烦的是对于边界不对齐的b,还得将其合成4字节(一部分是来自一个四字节中的b0、b1和b2,另一部分来自另一个4字节中的b3),而这又增加了程序的复杂性,即需要更多的指令来完成。
以上分析可以看出,采用字节对齐能提高系统性能。而编译器在编译程序时,也会根据需要选择不同的指令来完成对数据的存取操作。
本文分享自 nginx遇上redis 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!