Detailed analysis of C and C++ data alignment

  • 2020-04-02 01:45:53
  • OfStack

The Data Alignment

On the data alignment problem, now more or less some contact, briefly say their own views.

1. Aligned background

Big end and small end question it is necessary to introduce here, the computer inside each address unit corresponds to a byte, a byte is 8 bit, for digits than 8-bit processor registers is greater than the width of a byte, 16 bit short type variable x, for example, is in memory address 0 x0010, the value of x is 0 x1122, 0 x11 for high byte, 0 x22 for low byte, common X86 structure is small end model, a lot of ARM and DSP are small end model, while the KEIL C51 to big end mode. Memory space is carried out in accordance with the byte division, access to any type of variables can be theoretically from any address, but in fact, often in a particular access specific variable access memory address, which requires various types of data according to certain rules in space arrangement, rather than the order, this is the alignment.

2. Reasons for alignment

Different hardware platforms treat storage space very differently, and some platforms can only access certain types of data from certain addresses. This may not be the case on other platforms, but it is most common to see a loss of access efficiency if data storage is not aligned to the requirements of their platform. Some platforms such as every time I read from my address, if an int type (assuming 32-bit) as if in my address, they can read a read cycle, if stored in address starts, is likely to need 2 read cycle, and the results of two readout of high and low together to get the int data bytes. Obviously there's a big drop in read efficiency. It is also a game of space and time.

3. Realization of alignment

In general, we do not need to consider the impact of alignment when we write code. We rely on the compiler to choose the appropriate alignment strategy for us. We can also specify the method of data alignment by passing precompilation instructions to the compiler.

Take sizeof method of struct data structure as an example. The environment is Mac OS X 64-bit kernel. The structure is defined as follows:

Struct A {
Int a;
Char b;
Short c;
};

Struct {B
Char b;
Int a;
Short c;
};

# pragma pack (2)
{C struct
Char b;
Int a;
Short c;
};
# pragma pack ()

# pragma pack (1)
Struct D {
Char b;
Int a;
Short c;
};
# pragma pack ()

Int main(int argc, char** argv)
{
Printf ("size of struct A: %lu \n", sizeof(struct A));
Printf ("size of struct B: %lu \n", sizeof(struct B));
Printf ("size of struct C: %lu \n", sizeof(struct C));
Printf ("size of struct D: %lu \n", sizeof(struct D));
Return 0;
}

Output:
Size of struct A: 8
Size of struct B: 12
Size of struct C: 8
Size of struct D: 7

The structure contains an int of 4 bytes, a char of 1 byte and a short of 2 bytes. The memory space used adds up to 7 bytes, but when sizeof was actually used, it was found that the memory footprint was different between the structures.

There are several things to be said about alignment:
(1) the alignment value of the data type itself: the self-alignment value of the basic data type, char type is 1, short type is 2, int, float, double is 4;

(2) specify alignment value: #pragma pack(value);

(3) self-aligned value of a structure or class: the value whose self-aligned value is the largest in its members;

(4) valid alignment values for data members, structs, and classes: self-aligned values or smaller values in the specified alignment values.

For the members of a specific data structure and its own alignment, the effective alignment value N will ultimately determine the value of the way in which the data is stored.

Here's an analysis of the above example:
Struct {B
Char b;
Int a;
Short c;
};

Assume that B starting address space x0000 0, the default alignment value is 4 (here have a question want to ask you, to me is a 64 - bit kernel, but my default alignment is 4), the first member variable self alignment value is 1, B is smaller than the default value so effective alignment value is 1, store address 0 x0000%1 = 0, the second member variable a, its alignment value is 4, the starting address of the store to 0 x0004 x0007 this four consecutive bytes 0 Spaces, 0 x0004%4 = 0, a third variable c, its alignment value is 2, The starting address is 0x0008 to 0x0009, which also meets the requirements. The self-alignment value of structure B is the maximum alignment value in the variable (B) 4, (10+2) % 4=0, so 0x000A to 0x000B are also occupied by structure B.
Schematic diagram in memory:
B -
A, a, a, a
C c

# pragma pack (2)
{C struct
Char b;
Int a;
Short c;
};
# pragma pack ()

First variable alignment of b value is 1, specify the alignment value is 2, effective alignment value is 1, b in 0 x0000, a self alignment value is 4, is greater than the specified alignment value, all effective alignment value is 2, a possession x0003 x0002 bytes to 0, 0, 0 x0004, 0 x0005 four consecutive bytes, alignment of c value of 2, so effective alignment value is 2, order in 0 x0006, 0 x0007. The self-alignment value of structure C is 4, so the effective alignment value is 2, 8/2 =0.
Schematic diagram in memory:
B -
A. a.
A. a.
C c

It's a lot easier when you think of a schematic in memory.


Related articles: