What is memory alignment

To illustrate the problem, look at the following small program: theoretically, on 32-bit systems, ints account for 4 bytes and chars account for 1 byte, so putting them in a structure should account for 4+1=5 bytes; But in reality, running the program yields 8 bytes, which is what memory alignment is all about.

> #include<stdio.h> > struct{ > int x; > char y; > }s; > > int main() > { > printf("%d\n",sizeof(s); // output 8 > return 0; >}Copy the code

Memory space in the modern computers are divided according to the byte, theoretically seems to access to any type of variables can be from any address, but the actual computer system of the basic types of data in memory to store the location of the limited, they can ask the data of the first address is the value of k of a certain number (usually it is 4 or 8) multiples, This is called memory alignment.

Why memory alignment

Memory is based on bytes, while CPU accesses data in blocks rather than bytes. Frequent access to unaligned data can significantly degrade CPU performance. Byte alignment reduces the number of CPU accesses. The purpose of this space – for – time swap is to reduce CPU overhead. CPU access is in blocks, and access to unaligned data may start in one block and end in another. In this way, the middle may be combined together through complex operations, reducing efficiency. Byte alignment improves CPU access speed.

Without memory alignment, data can be stored arbitrarily. Now an int variable is stored in a four-byte address starting at address 1. The first 4-byte block is read from address 0, discarding unwanted bits (address 0), then the next 4-byte block is read from address 4, discarding unwanted bits (addresses 5, 6, and 7), and merging the remaining two blocks into a register. It takes a lot of work.

Now with memory aligned, int data can only be stored in memory that follows the alignment rules, such as memory starting at address 0. So now the processor can read the data once when it fetches the data, and does not need to do additional operations, improving efficiency

The principle of internal alignment exists in the structure

1. Alignment rules for data members: The first data member of a struct (or union) is placed at offset 0, and the starting position of each data member is from the size of the member or the size of the member’s children (as long as the member has child members, such as arrays). Structure, etc.) (for example, if int is 4 bytes, it is stored from the address that is a multiple of 4.

2. Struct as members: If a struct has members, then the members are stored from an integer multiple of the size of the largest element in the struct.

3. Finishing off: the total sizeof the structure, the result of sizeof, must be an integer multiple of its largest internal member.

Let’s look at a couple of examples

struct XJStruct1 { double a; // 8 [0 7] char b; // 1 [8] int c; // 4 (9 10 11 [12 13 14 15] short d; // 2 [16 17] 24 }struct1; ! [screenshots 2021-06-13 Afternoon 3.12.33. PNG] (HTTP: / / https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/569549afac0d471c968ac05de36c29b2~tplv-k3u1fbpfcp-waterm ark.image) struct XJStruct2 { double a; // 8 [0 7] int b; // 4 [8 9 10 11] char c; // 1 [12] short d; // 2 (13 [14 15] 16 }struct2;Copy the code

Here sort out some basic data types in different systems under the byte size, convenient for everyone to view.

At first glance, the two structures are almost identical, so it looks like they take up the same amount of memory. In fact, the order of the member variables also affects the size of the structure. Let’s run to verify this

Not surprisingly, the bytes are different when printed and the problem lies in the type and order of b and C. Double is 8 bytes in size, and according to rule 1, the A member variable will occupy the first 8 bytes from the first address. That’s the address from 0x00 to 0x07. Char (size 1) is a multiple of 1, occupying one byte 0x08, and the singular member variable c is an int (size 4). Char (size 10) is not a multiple of 4 and does not satisfy rule 1. Therefore, the member variable B will fill three positions, that is, the address unit occupying 0x08 to 0x11, and the member variable C will occupy four memory units starting from 0x12 to 0x15. Similarly, according to rule 1, it can be concluded that the member variable D occupies a memory cell from 0x16 to 0x08, occupying a total of 18 bytes. Finally, we wrap things up: the total size of the structure must be an integer multiple of its largest internal member. The maximum internal member is double 8 bytes, and the total size of the structure can be calculated as 24; Similarly, the memory of the second structure is 16.

What if there are structure member variables in the structure?

According to rule 1, it can be seen that the first five variables occupy 24 memory units. For the structure member STR, its maximum internal member is double 8 bytes, and 24 is a multiple of 8, which conforms to rule 1. STR occupies the next 24 byte units. At this point, the structure occupies 48 memory units in total. According to rule 3, the maximum member of XJStruct2 is XJStruct1 STR with 24 bytes, which conforms to the rule. Let’s verify the result with code

conclusion

In general, memory alignment specifies a set of rules for the proper use of memory space for the purpose of improving access efficiency. The system through certain code filling to achieve in a command to complete each member of the access, no longer repeat the combination and split. So as to achieve the effect of space for time, improve efficiency.