标题：对齐
注音
duì qí
英文
align [ə'laɪn] 1.及物动词[+objects]对齐2.成一条线
注释
⒈使两个以上事物配合或接触得整齐。
⒉将[两个或更多的机器部件，尤指应互相平行或成行的部件]排到正确的位置或方向。如：把轮子对齐。
（内存）对齐
平台原因（移植原因）不是所有的硬件平台都能访问任意地址上的任意数据的；某些硬
件平台只能在某些地址处取某些特定类型的数据，否则抛出硬件异常。
性能原因数据结构（尤其是栈）应该尽可能地在自然边界上对齐。原因在于，为了访问
未对齐的内存，处理器需要作两次内存访问；而对齐的内存访问仅需要一次访问。
对齐规则每个特定平台上的编译器都有自己的默认“对齐系数”（也叫对齐模数）。程序员可以通过预编
译命令#pragma pack(n），n=1,2,4,8,16 来改变这一系数，其中的n 就是你要指定的“对齐系数”。
规则⒈数据成员对齐规则：结构（struct）（或联合（union））的数据成员，第一个数据成员放在offset
为0 的地方，以后每个数据成员的对齐按照#pragma pack 指定的数值和这个数据成员自身长
度中，比较小的那个进行。
⒉结构(或联合）的整体对齐规则：在数据成员完成各自对齐之后，结构（或联合）本身也要进
行对齐，对齐将按照#pragma pack 指定的数值和结构（或联合）最大数据成员长度中，比较小
的那个进行。
⒊结合1、2 可推断：当#pragma pack 的n 值等于或超过所有数据成员长度的时候，这个n
值的大小将不产生任何效果。
PS对齐
Photoshop软件操作中，选择该复选框时，表示在图像复制过程中不论操作多少次，所复制的图像仍然是一幅完整的图像；若取消选择该复选框，则每次停笔再画时，就会被认为是另一种复制，所复制的图像就不再是一幅完整的图像，此时适用于多次复制同一幅图像。
计算机内存中的对齐
一、什么是对齐，以及为什么要对齐⒈现代计算机中内存空间都是按照byte划分的，从理论上讲似乎对任何类型的变量的访问可以从任何地址开始，但实际情况是在访问特定变量的时候经常在特定的内存地址访问，这就需要各类型数据按照一定的规则在空间上排列，而不是顺序的一个接一个的排放，这就是对齐。
⒉对齐的作用和原因：各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况， 但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐，会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始，如果一个int型（假设为 32位）如果存放在偶地址开始的地方，那么一个读周期就可以读出，而如果存放在奇地址开始的地方，就可能会需要2个读周期，并对两次读出的结果的高低 字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。
二、对齐的实现通常，我们写程序的时候，不需要考虑对齐问题。编译器会替我们选择适合目标平台的对齐策略。当然，我们也可以通知给编译器传递预编译指令而改变对指定数据的对齐方法。
但是，正因为我们一般不需要关心这个问题，所以因为编辑器对数据存放做了对齐，而我们不了解的话，常常会对一些问题感到迷惑。最常见的就是struct数据结构的sizeof结果，出乎意料。为此，我们需要对对齐算法所了解。
对齐的算法：
由于各个平台和编译器的不同，现以本人使用的gcc version 3.2.2编译器（32位x86平台）为例子，来讨论编译器对struct数据结构中的各成员如何进行对齐的。
设结构体如下定义：
struct A {
int a;
char b;
short c;
};
结构体A中包含了4字节长度的int一个，1字节长度的char一个和2字节长度的short型数据一个。所以A用到的空间应该是7字节。但是因为编译器要对数据成员在空间上进行对齐。
所以使用sizeof(strcut A）值为8。
现在把该结构体调整成员变量的顺序。
struct B {
char b;
int a;
short c;
};
这时候同样是总共7个字节的变量，但是sizeof(struct B）的值却是12。
下面我们使用预编译指令#pragma pack (value）来告诉编译器，使用我们指定的对齐值来取代缺省的。
#progma pack ⑵/*指定按2字节对齐*/
struct C {
char b;
int a;
short c;
};
#progma pack () /*取消指定对齐，恢复缺省对齐*/
sizeof(struct C）值是8。
修改对齐值为1：
#progma pack ⑴/*指定按1字节对齐*/
struct D {
char b;
int a;
short c;
};
#progma pack () /*取消指定对齐，恢复缺省对齐*/
sizeof(struct D）值为7。
对于char型数据，其自身对齐值为1，对于short型为2，对于int,float,double类型，其自身对齐值为4，单位字节。
这里面有四个概念值：
1）数据类型自身的对齐值：就是上面交代的基本数据类型的自身对齐值。
2）指定对齐值：#pragma pack (value）时的指定对齐值value。
3）结构体或者类的自身对齐值：其成员中自身对齐值最大的那个值。
4）数据成员、结构体和类的有效对齐值：自身对齐值和指定对齐值中较小的那个值。
有了这些值，我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值，最重要。有效对齐N，就是表示“对齐在N上”，也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是 数据结构的起始地址。结构体的成员变量要对齐排放，结构体本身也要根据自身的有效对齐值圆整（就是结构体成员变量占用总长度需要是对结构体有效对齐值的整 数倍，结合下面例子理解）。这样就不难理解上面的几个例子的值了。
例子分析：
分析例子B；
struct B {
char b;
int a;
short c;
};
假设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值，在笔者环境下，该值默认为4。第一个成员变量b的自身对齐值是1，比指定或者默认指 定对齐值4小，所以其有效对齐值为1，所以其存放地址0x0000符合0x0000%1=0.第二个成员变量a，其自身对齐值为4，所以有效对齐值也为 4，所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中，复核0x0004%4=0，且紧靠第一个变量。第三个变量c，自身对齐 值为2，所以有效对齐值也是2，可以存放在0x0008到0x0009这两个字节空间中，符合0x0008%2=0。所以从0x0000到0x0009存 放的都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值（这里是b）所以就是4，所以结构体的有效对齐值也是4。根据结构体圆整的要求， 0x0009到0x0000=10字节，（10+2）%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B 共有12个字节，sizeof(struct B)=12;
同理，分析上面例子C：
#pragma pack ⑵/*指定按2字节对齐*/
struct C {
char b;
int a;
short c;
};
#pragma pack () /*取消指定对齐，恢复缺省对齐*/
第一个变量b的自身对齐值为1，指定对齐值为2，所以，其有效对齐值为1，假设C从0x0000开始，那么b存放在0x0000，符合0x0000%1= 0；第二个变量，自身对齐值为4，指定对齐值为2，所以有效对齐值为2，所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续 字节中，符合0x0002%2=0。第三个变量c的自身对齐值为2，所以有效对齐值为2，顺序存放
在0x0006、0x0007中，符合0x0006%2=0。所以从0x0000到0x00007共八字节存放的是C的变量。又C的自身对齐值为4，所以 C的有效对齐值为2。又8%2=0,C只占用0x0000到0x0007的八个字节。所以sizeof(struct C)=8.
有 了以上的解释，相信你对C语言的字节对齐概念应该有了清楚的认识了吧。在网络程序中，掌握这个概念可是很重要的喔，在不同平台之间（比如在Windows 和Linux之间）传递2进制流（比如结构体），那么在这两个平台间必须要定义相同的对齐方式，不然莫名其妙的出了一些错，可是很难排查的哦^_^。[1]