系统要求某些基本类型数据按照特定的内存地址对齐方式(如int类型按照4字节的倍数对齐,short类型按照2字节的倍数对齐等)。当然,这些可以优化以在填充方面浪费最少的空间。
我的问题是为什么GCC不自动完成这个操作?更明显的启发式方法(将变量按照占用空间从大到小排序)有什么缺陷吗?是否有些代码依赖于其结构体的物理顺序(这是一个好的想法)?
我只是问一下,因为GCC在很多方面都进行了超级优化,但在这方面却没有,我想这里肯定有一些比较酷的解释(而我并不知情)。
系统要求某些基本类型数据按照特定的内存地址对齐方式(如int类型按照4字节的倍数对齐,short类型按照2字节的倍数对齐等)。当然,这些可以优化以在填充方面浪费最少的空间。
我的问题是为什么GCC不自动完成这个操作?更明显的启发式方法(将变量按照占用空间从大到小排序)有什么缺陷吗?是否有些代码依赖于其结构体的物理顺序(这是一个好的想法)?
我只是问一下,因为GCC在很多方面都进行了超级优化,但在这方面却没有,我想这里肯定有一些比较酷的解释(而我并不知情)。
gcc不会重新排列结构体的元素,因为那样会违反C标准。C99标准的6.7.2.1节规定:
在结构体对象内,非位域成员和位域所在单元的地址按照它们声明的顺序递增。
结构体经常被用作二进制文件格式和网络协议的打包顺序的表示。如果这样做,将会破坏它们的功能。此外,不同的编译器会以不同的方式进行优化,无法将两种代码链接在一起。这根本行不通。
gcc SVN确实有一种结构重组优化(-fipa-struct-reorg),但它需要整个程序的分析,目前并不是很强大。
并不是说这是一个好主意,但你可以编写依赖于结构体成员顺序的代码。例如,作为一种hack,人们经常将指向结构体的指针强制转换为其中某个字段的类型,然后使用指针算术运算来访问该字段。对我来说,这是一个非常危险的想法,但我已经看到它被使用了,特别是在C++中,当一个变量被声明为私有时,可以通过这种方式使其在第三方库的类中公开访问而不被公开封装。重新排序成员会完全破坏这种实现。
因为像你提到的对齐问题,C编译器不会自动精确地打包结构体。在x86上,没有按字边界(大多数CPU上的32位)访问会带来沉重的惩罚,并在RISC架构上引起致命陷阱。
-fipa-struct-reorg
选项。是否有GCC关键字允许结构重排? - phuclv