其实这篇文章,原作者是http://www.cnblogs.com/Steak/p/3660403.html
我之所以再写一遍,是想加一些我自己的理解,以方便日后自己更好理解罢了。
先看下面的代码:
变量int iTest为4字节,char cTest为1字节,所占用内存应该为5字节。但现在为8字节。那么多出来那3字节就涉及到内存对齐了。我们先看看这个结构体在内在中的分布:
0 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x10 | iTest | cTest | 空位 | ||||||||||||
0x20 |
由表格中可以看出,iTest占4字节,cTest占1个字节,另外还有3字节的空位。这是因为处理结构体变量时,需要一次读入32位,也就是4个字节。如果没有那3个空位,那么内存就读越界了。那么你可能会说,是哪个混蛋规定处理结构体时,需要一次读4个字节,这不是没事找事做么。那这就要涉及到硬件平台相关和性能问题。平台问题:如果某种CPU只能读4个字节(只是假如...)。性能问题:假如你每次读1个字节,那么读iTest时是不是要读4次呢??当然编译器不一定是这么处理的。但性能的影响大概与之相类似,需要进行更多的运算处理。其实可以设置编译器每次读入的字节数
#include <iostream> using namespace std; #pragma pack(1) //1 2 4 6 8 ...决定每次处理结构体变量读入的字节数 typedef struct test { int iTest; char cTest; }S_TEST; int main(int argc,char *argv[]) { cout<<"size:"<<sizeof(S_TEST)<<endl; }
则结果为size:5
我判断内存对齐的方法:在结构体内,按顺序取变量,每次只读4字节,如果取到了1个以后变量并且把某个变量截断了,就要考虑内存对齐了。
例1
struct test { char a; int b; }
按顺序读入4字节,取到了变量a和3/4个变量b,即取到了两个变量并且把b给截断了。所以在截断的地方a和b之间把内存补齐为4。故a后面有3字节的空位。
例2
struct test { double f; char a; char b; char c; int d; char e; }
按顺序读入4字节,只取到4/8个变量f,再读入4字节,取到一个变量f,没有截断任何变量,不用考虑内存对齐。再读入4字节,取到变量a,b,c,1/4d,c与d之间需要考虑内存对齐。
再读入4字节,取到d.再读入4字节,取到e还多了,需要考虑内存对齐。
所以把上面的代码改一下:
struct test { double f; char a; char b; char c; char e; int d; }
则不需要考虑内存对齐。
事实上,内存对齐对程序员是透明的。即在写程序时,其实我们不用去管这些东西。按我的习惯,把占用内存最小的变量依次声明(先把所有char型变量声明完,再到int,double......),可以避免这些问题。但如果写底层,就要注意这些了。