31

For example, I have a class,

class naive {
public:
    char a;
    long long b;
    char c;
    int d;
};

and according to my testing program, a to d are built one after another, like

a-------
bbbbbbbb
c---dddd

- means unused.

Why does not C++ make it tighter, like

ac--dddd
bbbbbbbb
phuclv
  • 37,963
  • 15
  • 156
  • 475
Dante May Code
  • 11,177
  • 9
  • 49
  • 81
  • 5
    `bbbbbbbbddddac` would be even tighter and you don't have to pad 2 bytes behind – phuclv Apr 18 '15 at 09:47
  • You have to pad 2 bytes behind anyways in order to satisfy alignment of the whole struct @phuclv – MrIo Mar 30 '23 at 11:00

1 Answers1

56

Class and struct members are required by the standard to be stored in memory in the same order in which they are declared. So in your example, it wouldn't be possible for d to appear before b.

Also, most architectures prefer that multi-byte types are aligned on 4- or 8-byte boundaries. So all the compiler can do is leave empty padding bytes between the class members.

You can minimize padding by reordering the members yourself, in increasing or decreasing size order. Or your compiler might have a #pragma pack option or something similar, which will seek to minimize padding at the possible expense of performance and code size. Read the docs for your compiler.

Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • 12
    The GCC equivalent of `#pragma pack` is `__attribute__ ((packed))`. In C++11 this becomes standardized, with the attribute `alignas`. – R. Martinho Fernandes Jul 18 '11 at 09:15
  • 8
    Specifically, the requirement for data members being in the same order in memory is codified in 9.2.12 (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. [...]) of the ISO/IEC 14882:2003 standard. – Martin Sojka Jul 18 '11 at 09:22
  • @Martinho, do you have any more information about alignas? I tried to google it but got no clear results. This would be very helpful for me. – KillianDS Jul 18 '11 at 09:47
  • 1
    @Killian: You can find it in the latest publicly available standard draft: [N3242](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf). Look for section 7.6.2. – R. Martinho Fernandes Jul 18 '11 at 09:49
  • 1
    What is the reason for not allowing the compiler to rearrange the members in memory? – Kevin Panko Jul 18 '11 at 16:19
  • 3
    @Kevin - The C standard says so, because that is the way it worked when C was standardized. Presumably some "clever" code took advantage of this. – Bo Persson Jul 18 '11 at 17:23
  • 7
    @Kevin - A common old-school trick for declaring objects with a header and variable length body is to end the header structure with a dummy array of length one (or length zero if the compiler allows it), and then malloc sizeof(header)+length_of_body. You can then index into the body using the dummy array. If the dummy could be reordered to the beginning of the structure, this wouldn't work. – Russell Borogove Jul 18 '11 at 17:36
  • 6
    @Kevin: For the most part, so you can represent RAM areas mapped to hardware registers, network protocols, file formats and similar structures as C structs. – Martin Sojka Jul 18 '11 at 22:00
  • Can this statement be clarified? "minimize padding at the possible expense of performance and code size". The compiler could take more time but won't lesser padding lead to lesser code size and hence, better run time performance? – Hari May 07 '20 at 06:01