1. What is memory alignment

Int = 4 bytes; char = 1 bytes; int = 4 bytes; char =5 bytes; int = 4 bytes;

struct Struct {
    int a;  / / 4
    char b; / / 1
}struct4;

NSLog(@"%lu".sizeof(struct4)); // Output is 8
Copy the code

Memory space in the computer 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.

2. Why memory alignment

Platform reasons (migration reasons) : Not all hardware platforms can access arbitrary data at arbitrary addresses; Some hardware platforms can only fetch certain types of data at certain addresses or throw hardware exceptions.

Our premise is that the computer’s processor reads in chunks of a certain size.

Alignment has to do with where the data is in memory. If the memory address of a variable is exactly an integer multiple of its length, it is said to be naturally aligned. For example, an integer variable (4 bytes) with an address of 0x00000008 is naturally aligned.

Now suppose that an integer variable (4 bytes) is not naturally aligned, its starting address falls at 0x00000002 (blue area), and the processor wants to access its value, reading in 4-byte chunks, starting at 0x00 in the figure, reading in 4-byte sizes, and reading up to 0x03

After such a read, instead of fetching the integer we want to access, the processor then reads down again, offsetting it by 4 bytes, starting at 0x04 and ending at 0x07

At this point, the processor can read the memory data we need to access, and there is a process of culling and merging. In the example above, it takes two reads to get the data we want.

What if it’s memory aligned?

As can be seen from the figure above, the corresponding data can be obtained as long as it is read once.

Therefore, it can be concluded that memory alignment will affect the efficiency of data reading. In addition, different memory access granularity also has different effects on the same task, which we will not discuss here.

3. Align memory

  1. Data member alignment rules: Structure (struct)(or combined (union), the first data member is placed inoffsetAt 0 (the location of the first address), the starting location of each subsequent data member must start with an integer multiple of the size of the member or its children (as long as the member has children, such as arrays, structures, etc.) (e.gintfor4Bytes, from4An integer multiple of the address is stored.
  2. Struct as members: If a structure has some struct members, the struct members are stored from an integer multiple of the size of the largest element in the structure.struct aThe entitiesstruct b.bAre there inchar,intdoubleStudent: equal elements, thatbShould be from8Integer multiples of start storage.
  3. Finishing off: The total size of the structure, i.esizeofThe result must be an integer multiple of the largest internal member, and the less must be made up.

As I understand it:

  • For rule 1, the starting position of each data member is an integer multiple of its own size.
  • For rule 2, the starting position of a structure’s member variable is determined by the largest element of its member variable.

Let’s look at a simple example:

struct TestStruct {
    double a;       / / 8
    char b;         / / 1
    int c;          / / 4
    short d;        / / 2
}struct1;
Copy the code

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 to be 24.

Finally, we use code to verify:

What happens if a structure member variable exists in a structure?

struct TestStruct2 {
    double a; / / 8
    int b;    / / 4
    char c;   / / 1
    short d;  / / 2
    int e;    / / 4
    struct TestStruct1 str;
}struct2;
Copy the code

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 TestStruct2 is TestStruct1 STR with 24 bytes, which complies with the rule. Let’s verify the result with code

4. To summarize

In essence, memory alignment is to customize a set of rules to make proper use of memory space and improve memory access efficiency. By adding some padding, the compiler allows each member to be accessed in a single instruction, rather than requiring multiple accesses to concatenate. It’s a process of exchanging space for time.