在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字节对齐