您的位置:首页 > 其它

GCC 4.7+ version 字节对齐

2013-09-25 01:42 218 查看
1、位域对齐

3.7版本之后GCC都默认使用了-mms-bitfields,此选项意义为使用Microsoft的方式进行对齐操作,其对齐策略为将对所有类型相同的位域合并到一起。与之相对的是GCC对其方式,其对齐策略为将所有位域合并到一起,并不区分位域类型。

如下例:

struct {
unsigned long long c : 1;
unsigned int a : 1;
unsigned int b : 1;
}


Mircrosoft对齐方式将合并类型相同的a、b,为之分配8个字节,而对于c,则单独分配8个字节,所以上述结构体在此对齐方式下大小为16.

GCC对齐方式将不区分类型合并所有的位域,并根据原类型中最大尺寸分配位域保存所需的字节数。譬如对于上述结构,最大尺寸为long long,所以上述结构体大小为8.

此结论可以通过为struct添加不同的GCC结构属性测试得到。

struct fields {
unsigned long long c :1;
unsigned int a :1;
unsigned int b :1;
//}__attribute__ ((__ms_struct__)); //用于测试Microsoft对齐方式。得到sizeof(fields)结果为16。
//}__attribute__ ((__gcc_struct__));//用于测试GCC对齐方式。得到sizeof(fields)结果为8。


从gcc与ms(Microsoft)的对齐策略可见,gcc的对齐方式相对更加节约存储空间。

2、结构对齐

先看一个结构体:

struct struct_ {
char first[1];
long int second;
char third[1];
};


此结构体使用默认的GCC选项编译后,既默认使用-mms-bitfields选项的情况下,将得到大小为9字节的存储空间。

这是因为对于32位操作系统,GCC默认对齐字节为4字节,在使用MS结构对齐策略的情况下,GCC在处理第一个变量时保持其尺寸不变,既为1字节,在处理第二个变量时同样保持其尺寸不变,既为4字节,在处理第三个也是最后一个变量时,扩展其尺寸至对齐尺寸4字节。因此最后得到的总结构大小为1+4+4=9字节。

总而言之,MS的对齐策略仅对结构中最后一个变量起作用。

如果关闭默认的MS对齐策略(通过为GCC添加-mno-ms-bitfields参数),转而使用GCC的对齐策略,上述结构的尺寸将会是多少?

测试的结果是:12。为何?这是因为GCC将对齐策略应用在了结构体中的每个变量上,对于非4字节的整数倍的char类型变量first[1]、third[2],GCC都将其扩展为4个字节,对于second,由于其类型大小为4字节,所以GCC保持其大小不变。扩展完成后,结构体的大小为:4+4+4=12字节。

3、强制设定对齐方式

字节对齐有利于整块读取数据,提高数据吞吐量,但是这是在牺牲存空间的情况下得到的,而在实际应用中,比如网络环境下,为了减少数据传输量,我们并不希望使用字节对齐方式,这时需要关闭字节对齐。

在程序的移植过程中,比如将32bit系统下的程序移植到64bit系统下,原有的字节对齐方式可能无法达到提高数据吞吐的目的,因此,我们需要更改字节对齐方式。

如何关闭?如何更改?

GCC提供了几种方式:

3.1、通过属性方式改变:

__attribute__ ((__ms_struct__)) 指定使用MS对齐策略

__attribute__ ((__gcc_struct__)) 指定使用GCC对齐策略

__attribute__ ((__packed__)) 指定使用最少存储空间对齐策略:合并所有位、对变量使用单字节方式对齐。

3.2、通过标识符声明方式:

#pragma pack(N) 设定对齐方式为N字节。

#pragma pack() 设定对齐方式为上一次对齐方式。

#pragma pack(push[, n]) 保存当前对齐方式并设置对齐方式为N字节。

#pragma pack(pop) 恢复最近一次保存的对齐方式。

对于i386构架,GCC专门提供了如下3个声明控制对齐方式:

#pragma ms_struct on 启用MS对齐方式。

#pragma ms_struct off 关闭MS对齐方式。

#pragma ms_struct reset 重置当前对齐方式为默认对齐方式。

3.3 通过设置GCC编译参数方式:
-fpack-struct[=N] 设定对齐方式为N字节对齐,不带”=N“时默认为4字节对齐。
-mno-ms-bitfields 关闭MS对齐策略,使用GCC对齐策略。

参考资料:
1、MinGW-w64 - for 32 and 64 bit Windows
2、GCC 4.7.0 breaks __attribute__((packed)) behavior on...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: