![]() |
1
6
如果您能从存储中挤出的每个单词都是关键的,那么我建议您手工优化结构。一个工具可以为您优化地安排成员,但是它不知道,例如,您存储在16位中的这个值实际上永远不会超过1024,所以您可以为 这 价值超过 在这里 … 所以在这项工作中,人类几乎肯定会打败机器人。 [编辑]但似乎您真的不想手动优化每个架构的结构。也许你真的有很多架构需要支持? 我确实认为这个问题不适合一般的解决方案,但是您可以将您的域知识编码成一个定制的perl/python/something脚本,该脚本为每个体系结构生成结构定义。 此外,如果所有成员的大小都是2的幂,那么您只需按大小对成员进行排序(第一个最大的)即可获得最佳打包。在这种情况下,您只需使用传统的基于宏的结构构建——类似于:
|
![]() |
2
6
Perl安装中通常包含一个名为pstruc的Perl脚本。脚本将转储结构成员偏移量和大小。您可以修改pstruc,也可以将其输出作为一个起点,用于生成一个实用程序,以您想要的方式打包您的结构。
|
![]() |
3
2
大多数C编译器不会这样做,因为您可以做一些奇怪的事情(比如获取结构中元素的地址,然后使用指针魔术访问其余的,绕过编译器)。一个著名的例子是amigaos中的双链接列表,它使用守护节点作为列表的头和尾(这使得遍历列表时可以避免ifs)。守护者头节点
因此,最好的办法可能是将结构编写为伪代码,然后编写一个预处理器脚本,从中创建真正的结构。 |
![]() |
4
0
看看pragma pack。这将更改编译器如何对齐结构中的元素。你可以用它来强迫他们紧密地包装在一起,没有空间。 |
![]() |
5
0
它也将依赖于平台/编译器。如前所述,大多数编译器将所有内容填充为4字节对齐(或更糟!),假设一个结构有两条短裤和一条长短裤:
将占用12个字节(填充2*2个字节)。 重新排序为
仍然需要12个字节,因为编译器会填充它以使数据访问更快(这是大多数桌面的默认设置,因为它们更喜欢快速访问而不是内存使用)。您的嵌入式系统有不同的需求,因此无论怎样,您都必须使用pragma包。 至于要重新排序的工具,我只需(手动)重新组织结构布局,以便将不同类型放在一起。先把所有的短裤都穿好,然后把所有的长筒袜都穿上,等等。如果你想把包装做好,不管怎样,这就是工具所能做的。在类型之间的转换点中间可能有2个字节的填充,但我认为这不值得担心。 |
![]() |
6
0
编译器不能用自己的头重新排序结构中的字段。标准要求字段应按照定义的顺序进行布局。做其他事情可能会以微妙的方式破坏代码。 在您编写时,当然完全有可能生成某种以有效方式在字段中来回移动的代码生成器。但我更喜欢手动操作。 |
![]() |
7
0
想一想我该怎么做一个这样的工具…我想我先从调试信息开始。 从源头获取每个结构的大小是一件痛苦的事。它与编译器已经做的许多工作重叠。我对ELF还不够熟悉,无法准确地说出如何从调试二进制文件中提取结构大小信息,但我知道该信息存在,因为调试程序可以显示它。也许objdump或者binutils包中的其他东西可以为您提供这些琐碎的信息(至少对于使用elf的平台而言)。 在你得到信息后,剩下的就很简单了。将成员从大到小排序,尽量保持原始结构的顺序。使用Perl或python,甚至可以很容易地将其与源代码的其余部分交叉引用,甚至可能保留注释或ifdef,这取决于它们使用的多么干净。最大的痛苦是更改整个代码库中结构的所有初始化。伊克斯。 事情是这样的。听起来不错,但我不知道有这样的 现有的 这样做的工具,当你写你自己的时候…我认为您将能够手动重新排序程序中的大多数结构。 |
![]() |
8
0
我也有同样的问题。正如另一个答案所建议的,pstruc可能会有所帮助。但是,它确实提供了我们所需要的。实际上pstruc使用gcc提供的调试信息。我根据同样的想法写了另一个剧本。
必须使用存根调试信息生成程序集文件(
下面的脚本读取程序集文件,并在结构中添加额外字节时进行检测:
调用它的好方法:
|