在C语言中的预编译的字节对齐问题
通过# pragma包改变C编译器的字节对齐(N)在C语言中,结构是一种复合数据类型。它的组成元素可以是基本数据类型的变量(如int、长、浮、等),或一些数据单元的复合数据类型,如数组、结构、联合等结构中,编译器为每个部件的结构空间,根据其自然对齐的状态。每个成员按顺序存储在存储器中声明它们的顺序,和第一个成员的地址是作为整个结构的地址相同。
例如,以下结构的每个成员的空间分配是:
结构试验
{
char x1;
短X2;
浮X3;
char X4;
};
的结构,第一件x1,具有0的偏移和居第一字节。第二成员,X2,是短型的起始地址必须是2字节的边界,所以编译器填充X2和X1之间的一个空字节的结构,第三个成员国和第四个成员,X3,X4,落在他们的自然边界的地址不在他们需要额外的填充字节。在测试结构,成员X3需要4字节的对,这是在结构的所有成员最大的双细胞,因此测试结构的自然边界条件是4字节。编译器填充3个空字节成员X4之后。整个结构中占有12个字节的空间。改变C编译器默认的字节对齐
默认情况下,C编译器根据其自然边界条件为每个变量或数据单元分配空间:
使用伪指令#编译组(N),C编译器将N个字节对齐。
使用伪指令# pragma包()取消自定义字节对齐。
此外,还有以下方法:
__attribute((对齐(n))),允许对结构成员对齐的字节数的自然边界。如果在结构构件的长度大于n的最大成员的长度是一致的。
__attribute__(((包装)),对结构的优化调整的编制过程中,并使其与实际字节数。
上述n=1, 2, 4,8, 16…第一种方法比较常见。
应用实例
在网络协议编程,不同协议的数据包经常加工。一种方式是通过指针偏移获得各种信息,但这不仅是复杂的编程,但是一旦协议的变化,程序修改也更加困难。经过了解编译器的配置原理的结构空间,我们完全可以利用这一特性来定义我们的协议结构,并通过访问结构成员获得各种信息,这不仅简化了编程,而且变化的协议结构即使协议的变化,以便其他程序不需要修改,节省了时间和精力。下面的例子是TCP协议说明第一部分如何定义协议结构,其协议结构定义如下:
# pragma包(1) / /对齐到1字节
结构tcpheader
{
Short SrcPort; / / source port number 16
短dstport; / / 16目的端口号
Int SerialNo; / / 32位序列号
Int AckNo; / / 32确认号
unsigned char haderlen:4 / 4位的报头长度;
unsigned char保留1:4; / / 6预订4
unsigned char保留2:2; / / 6预订2
unsigned char URG:1;
无符号字符集:1;
unsigned char PSH:1;
无符号char:1;
无符号char SYN:1;
未签名的char鳍:1;
短windowsize; / / 16窗口大小
短tcpchksum; / / 16和TCP测试
短urgentpointer; / /指针16急救
};
# pragma(包) / /取消1字节对齐