Structural packaging. Is there an automatic way to do this?

Question : is there an automatic way to pack a structure?

Background

The packaging structure is very useful for reducing the memory cost of some fundamental data. Basically, this is a trick to achieve minimum memory cost by reordering the data internally. My question is, is there a way to do this? For example, I have a structure Foo here (assume 32 bit)

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

      

After auto-checking (either it's a script or not, native or not), I should get a version of Foo's optimization that:

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

      

This is just a toy example. Consider more complex situations below, it will be quite a job for manual reordering.

  • struct has a dependent structure:

    struct Foo {
      char* p;
      short number;
      MoreFoo more_foo // How to deal with this?
      char flag;     
    };
    
          

  • struct is in legacy code and you are not familiar with the codebase.

  • you want the code to be cross platform. Unfortunately, this trick is compiler dependent.

I do not consider using the "packed" attribute, as it will introduce some performance issue.

Could __attribute __ ((packed)) affect program performance?

+3


source to share


2 answers


In C ++ 03, you can grant compiler permission to reorder members by placing each member in a separate access section, for example:

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

      

Whether the particular compiler is this extra flexibility or not, I don't know.

This doesn't change the order of the declaration, it just reverses the memory order from the order of the declaration, so PaulMcKenzie refers to the order of initialization, which doesn't apply. (And I think he exaggerated the concern, it's very rare for member initializers to reference other subobjects in the first place)



How it works because it causes the following rule from 9.2) to no longer apply:

Non-static data members of a (non-unit) class that are declared without an intermediate access specifier are allocated so that later members have higher addresses in the class object. The distribution order of non-static data items separated by an access specifier is unspecified (11.1). The alignment requirements of the implementation may result in two adjacent elements not being allocated immediately next to each other; therefore, space may be required to manage virtual functions (10.3) and virtual base classes (10.1).

Also, it is questionable whether this works in C ++ 11, as the wording changed from "no intermediate access specifier" to "with the same access control":

Non-stationary data members (non-union) of a class with the same access control (section 11) are allocated in such a way that later members have higher addresses in the class object. The distribution of non-static data items with different access controls is not specified (clause 11). The alignment requirements of the implementation may result in two adjacent elements not being allocated immediately next to each other; therefore, space may be required to manage virtual functions (10.3) and virtual base classes (10.1).

+2


source


In C programming, automatic optimization of the structure is not possible because it would be contrary to how it was designed. C allows low-level access to hardware, in fact, it is only a step higher than assembly language. It is designed to generate dependent code that controls hardware.

With this in mind, unfortunately, you can only reorder the structure manually. You will probably need to find the size of all the attributes of the structure, like 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 arrange the structure based on those values.

+2


source







All Articles