qqibrow
qqibrow

Reputation: 3022

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

Question: Is there an automatic way to do structure packing?

Background:

Structure packing is very useful to reduce the memory cost of certain fundamental data. Basically it is the trick to achieve minimum memory cost by reordering the data inside. My question is that is there an auto way to do that? For example, I have a struct Foo here.(suppose 32bit)

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

After a auto check(either it is a script or not, native or not), I should get a memory-optimization version of Foo, which is:

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

This is just a toy example. Consider more difficult situations below, it would be quite a work for manual reordering.

  1. struct has dependent struct:

    struct Foo {
      char* p;
      short number;
      MoreFoo more_foo // How to deal with this?
      char flag;     
    };
    
  2. struct is in legacy code and you are not familiar with codebase.

  3. you want the code to be cross-platform. Sadly enough, this trick is compiler-dependent.

I am not considering using "packed" attribute since it will lead to some performance issue.

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

Upvotes: 5

Views: 1134

Answers (2)

Ben Voigt
Ben Voigt

Reputation: 283634

In C++03 you can give the compiler permission to reorder members by placing every one inside a separate access section, e.g.:

struct Foo
{
public:
  char* p;
public:
  short number;
public:
  MoreFoo more_foo;
public:
  char flag;     
};

Whether a particular compiler uses this additional flexibility or not I do not know.

This doesn't change the declaration order, it simply unlinks memory order from declaration order, so PaulMcKenzie's concern about initialization order does not apply. (And I think he overstated the concern; it is very rare for member initializers to refer to other subobjects in the first place)

The way this works is because it causes the following rule, from 9.2) to no longer have effect:

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

Also, it's questionable whether this still works in C++11, since the wording changed from "without an intervening access-specifier" to "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).

Upvotes: 3

buydadip
buydadip

Reputation: 9417

In C programming, automatic optimization of a struct is not possible because this would go against the very way it was designed. C allows low-level access to the hardware, in fact, it is only a step higher from assembly language. It is designed to create dependent code that controls hardware.

Given this, unfortunately, you can only re-order a struct manually. You would probably need to find the size of all the struct's attributes, as so:

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

And then order the struct based on these values.

Upvotes: 2

Related Questions