Structure Packing. Is there a automatic way to do it?
问题:有没有一个自动的方式来做结构包装?
背景:
结构打包对于降低某些基础数据的存储成本非常有用。基本上,这是通过重新排序内部数据来实现最小内存成本的技巧。我的问题是有自动的方法吗?例如,我这里有一个结构foo。(假设32位)
1 2 3 4 5 | struct Foo { char flag; char* p; short number; }; |
在自动检查之后(不管是不是脚本,本机的还是非本机的),我应该得到一个foo的内存优化版本,它是:
1 2 3 4 5 | struct Foo { char* p; short number; char flag; }; |
这只是一个玩具的例子。考虑到下面更困难的情况,这将是一个相当大的手工重新排序工作。
结构具有依赖结构:
1 2 3 4 5 6 | struct Foo { char* p; short number; MoreFoo more_foo // How to deal with this? char flag; }; |
结构位于旧代码中,您不熟悉代码库。
我不考虑使用"packed"属性,因为它会导致一些性能问题。
_uuu属性_uuuuu((packed))能否影响程序的性能?
在C++ 03中,您可以通过将每个成员放置在一个单独的访问段中,给编译器重新排序成员的权限,例如:
1 2 3 4 5 6 7 8 9 10 11 | struct Foo { public: char* p; public: short number; public: MoreFoo more_foo; public: char flag; }; |
我不知道特定的编译器是否使用了这种额外的灵活性。
这不会更改声明顺序,它只是将内存顺序与声明顺序断开链接,因此PaulMcKenzie对初始化顺序的关注不适用。(我认为他夸大了这种关注;成员初始值设定项一开始很少提及其他子对象)
其工作方式是因为它导致以下规则(从9.2)不再有效:
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
同样,这是否在C++ 11中仍然存在疑问,因为措辞从"没有中间访问指示符"改为"具有相同的访问控制":
Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (Clause 11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
在C编程中,结构的自动优化是不可能的,因为这与它的设计方式正好相反。C允许对硬件进行低级访问,事实上,它只比汇编语言高出一步。它设计用于创建控制硬件的依赖代码。
不幸的是,鉴于此,只能手动重新订购结构。您可能需要找到结构的所有属性的大小,因此:
1 2 3 4 5 6 7 8 | printf ("Size of char is %d ", sizeof (char)); printf ("Size of char* is %d ", sizeof (char*)); printf ("Size of short is %d ", sizeof (short)); printf ("Size of MoreFoo is %d ", sizeof (MoreFoo more_foo)); |
然后根据这些值对结构进行排序。