我花了几分钟手动重新排序结构中的字段,以减少填充效果[1],这感觉就像几分钟太多.我的直觉是说我的时间可能更好地花在编写Perl脚本上,或者为我做这种优化.
我的问题是这是否也是多余的; 是否已经有一些我不知道的工具,或者我应该能够启用[2]打包结构的一些编译器功能?
由于需要在几种不同的体系结构中进行一致优化,因此使用的任何工具都需要能够考虑不同的结构对齐和指针大小,这个问题更加复杂.
编辑:快速澄清 - 我想要做的是重新排序源代码中的字段,以避免填充,而不是"编译"结构,而不是填充编译.
编辑#2:另一个复杂因素:根据配置,某些数据类型的大小也可能会发生变化.显而易见的是针对不同体系结构的指针和指针差异,但也有浮点类型(16,32或64位,取决于'精确性'),校验和(8位或16位取决于"速度")和一些其他不明显的东西.
[1]所讨论的结构在嵌入式设备上被实例化了数千次,因此结构的每个4字节减少可能意味着该项目的go和no-go之间的差异.
[2]可用的编译器是GCC 3.*和4.*,Visual Studio,TCC,ARM ADS 1.2,RVCT 3.*以及其他一些更加模糊的编译器.
如果您可以挤出存储的每个单词都很重要,那么我必须建议手动优化结构.一个工具可以为你最佳地安排成员,但是它不知道,例如,你在这里以16位存储的这个值实际上永远不会超过1024,所以你可以窃取这个值的高6位这里 ......
因此,人类几乎肯定会在这份工作中击败机器人.
[编辑]但似乎你真的不想为每个架构手动优化你的结构.也许你真的有很多架构需要支持?
我认为这个问题不适用于一般解决方案,但您可能能够将您的领域知识编码为自定义Perl/Python/something脚本,为每个体系结构生成结构定义.
此外,如果所有成员的大小都是2的幂,那么只需按大小排序成员(最大的第一个),您就可以得到最佳的包装.在这种情况下,您可以使用良好的老式基于宏的结构构建 - 这样的事情:
#define MYSTRUCT_POINTERS \ Something* m_pSomeThing; \ OtherThing* m_pOtherThing; #define MYSTRUCT_FLOATS \ FLOAT m_aFloat; \ FLOAT m_bFloat; #if 64_BIT_POINTERS && 64_BIT_FLOATS #define MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_POINTERS MYSTRUCT_FLOATS #else if 64_BIT_POINTERS #define MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_POINTERS #else if 64_BIT_FLOATS #define MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_FLOATS #else #define MYSTRUCT_64_BIT_MEMBERS #endif // blah blah blah struct MyStruct { MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_32_BIT_MEMBERS MYSTRUCT_16_BIT_MEMBERS MYSTRUCT_8_BIT_MEMBERS };
有一个名为pstruct的Perl脚本通常包含在Perl安装中.该脚本将转储结构成员偏移量和大小.您可以修改pstruct或使用其输出作为制作实用程序的起点,该实用程序按您希望的方式打包您的结构.
$ cat foo.h struct foo { int x; char y; int b[5]; char c; }; $ pstruct foo.h struct foo { int foo.x 0 4 char foo.y 4 1 foo.b 8 20 char foo.c 28 1 }