结构包装。有没有自动的方法来做到这一点?

Structure Packing. Is there a automatic way to do it?

问题:有没有自动打包结构的方法?

背景:

Structure packing对于降低某些基本数据的内存开销非常有用。基本上,这是通过重新排序内部数据来实现最小内存成本的技巧。我的问题是有没有一种自动方法可以做到这一点?比如我这里有一个struct Foo(假设32bit)

struct Foo {     
  char flag;
  char* p;
  short number;
};

经过自动检查(是否为脚本,是否为本机),我应该得到 Foo 的内存优化版本,即:

struct Foo {
  char* p;
  short number;  
  char flag;     
};

这只是一个玩具示例。考虑以下更困难的情况,手动重新排序将是一项相当大的工作。

  1. 结构有依赖结构:

    struct Foo {
      char* p;
      short number;
      MoreFoo more_foo // How to deal with this?
      char flag;     
    };
    
  2. 结构在遗留代码中,您不熟悉代码库。

  3. 您希望代码是跨平台的。可悲的是,这个技巧依赖于编译器。

我不考虑使用 "packed" 属性,因为它会导致一些性能问题。

Can __attribute__((packed)) affect the performance of a program?

在 C 编程中,自动优化结构是不可能的,因为这会违背它的设计方式。 C 允许对硬件进行低级访问,实际上它比汇编语言高了一个台阶。它旨在创建控制硬件的相关代码。

鉴于此,不幸的是,您只能手动重新排序结构。您可能需要找到所有结构属性的大小,如下所示:

printf ("Size of char is %d\n", sizeof (char));
printf ("Size of char* is %d\n", sizeof (char*));
printf ("Size of short is %d\n", sizeof (short));
printf ("Size of MoreFoo is %d\n", sizeof (MoreFoo more_foo));

然后根据这些值对结构进行排序。

在 C++03 中,您可以通过将每个成员放在单独的访问部分中来授予编译器重新排序成员的权限,例如:

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 中是否仍然有效值得怀疑,因为措辞从 "without an intervening access-specifier" 更改为 "with the same access control":

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).