A major advantage of C language is its control of memory space. Of course, under the pressure of object-oriented languages, programmers prefer easy languages and do not like their own memory space.
However, the C language still has a strong vitality, especially in the operating system and embedded system, because the hardware needs to be operated directly, C language shows its powerful system, mechanism, and logic advantages.
The C language has always plagued beginners with memory control: byte alignment!
Look at a program:
Struct stexample <br/>{< br/> char a; <br/> char B <br/> short C; <br/> int D; <br/> }; /// // <br/> sizeof (char) = 1 <br/> sizeof (short) = 2 <br/> sizeof (INT) = 4 <br/> ///////////////////////////////// //// <br/> sizeof (struct stexample) = 8
The size of the stexample struct is 8 bytes. It looks as expected.
But the following example:
Struct stexample <br/>{< br/> char a; <br/> int B; <br/> short C; <br/> }; /// // <br/> sizeof (char) = 1 <br/> sizeof (short) = 2 <br/> sizeof (INT) = 4 <br/> ///////////////////////////////// //// <br/> sizeof (struct stexample) = 12 //?
The size of the stexample struct is changed to 12 bytes. Why is there a small number of elements, but the space occupied is 4 bytes more?
//////////////////////////////////////// //////////////////////////////////////// /////////
Let's take a look at four important basic concepts:
1. Alignment of data types:
: For char type data, its own alignment value is 1, for short type is 2, for int, float, double type, its own alignment value is 4, in bytes.
2. The alignment value of the struct or class:
: The value with the largest alignment value in the member.
3. Specify the alignment value:
: # Specify the alignment value when Pragma pack (value.
4. Valid alignment values of data members, struct and classes:
: The alignment value and the value smaller than the specified alignment value.
//////////////////////////////////////// //////////////////////////////////////// /////////
The valid alignment value n is the final value used to determine the data storage address. Valid alignment means "alignment on N", that is, the "Starting address for storing the data % n = 0 ".
Data variables in the data structure are discharged in the defined order. The starting address of the first data variable is the starting address of the data structure. The member variables of the struct must be aligned and discharged.
Example Analysis:
Struct stexample <br/>{< br/> char a; <br/> int B; <br/> short C; <br/> }; /// // <br/> sizeof (char) = 1 <br/> sizeof (short) = 2 <br/> sizeof (INT) = 4 <br/> ///////////////////////////////// //// <br/> sizeof (struct stexample) = 12 //?
Assume that stexample is discharged from the address space 0x0000. The alignment value is not defined in this example. In the author's environment, this value is 4 by default. Storage location of three members
1. the alignment value of the first member variable A is 1, which is smaller than the specified or default alignment value 4. Therefore, the valid alignment value is 1, therefore, the storage address 0x0000 is 0 x 0000% 1 = 0.
2. the alignment value of the second member variable B is 4, so the valid alignment value is 4. Therefore, it can only be stored in the four consecutive bytes from the starting address 0x0004 to 0x0007, review 0 x 0004% 4 = 0, which is close to the first variable.
3. The third variable C has its own alignment value of 2, so the valid alignment value is also 2, which can be stored in the space between 0x0008 and 0x0009, Which is 0 x 0008% 2 = 0.
Therefore, stexample content is stored from 0x0000 to 0x0009. Let's look at the data structure stexample's own alignment value as the maximum alignment value in its variable (here it is B) So it is 4, so the effective alignment value of the structure is also 4. According to the requirements of the structure, 0x0009 to 0x0000 = 10 bytes, (10 + 2) % 4 = 0. Therefore, 0x0000a to 0x000b is also occupied by the struct stexample. Therefore, stexample has 12 bytes from 0x0000 to 0x000b, and sizeof (struct stexample) = 12.
In fact, for this one, it will already satisfy the byte alignment, because its starting address is 0, so it must be alignment. The reason is to add two bytes later, this is because the compiler implements the access efficiency of structural arrays.
Imagine if we define an array of the stexample struct, the starting address of the first structure is 0, but what about the second structure? According to the definition of the array, all elements in the array are adjacent. If we do not add the size of the structure to an integer multiple of 4, the starting address of the next structure will be 0x0000a, this obviously cannot satisfy the address alignment of the structure, so we need to add the structure to an integer multiple of the valid alignment size.
In fact, for char data, its own alignment value is 1, short type is 2, Int, float, and double, and its own alignment value is 4, the alignment values of these existing types are also based on arrays, but their alignment values are also known because their lengths are known.
The following is an example:
# Pragma pack (2)/* specify to align by 2 bytes */<br/> struct stexample <br/>{< br/> char a; <br/> int B; <br/> short C; <br/>}; <br/> # pragma pack ()/* cancel the specified alignment, restore Default alignment */<br/> /////////////////////////////// ///// <br/> sizeof (struct stexample) = 8
1. the first variable A's own alignment value is 1 and the specified alignment value is 2. Therefore, the valid alignment value is 1. Assume that stexample starts from 0x0000, then a is stored in 0x0000, 0 x 0000% 1 = 0;
2. the second variable B has its own alignment value of 4 and the specified alignment value of 2. Therefore, the valid alignment value is 2, therefore, the sequence is stored in four consecutive bytes, namely 0x0002, 0x0003, 0x0004, and 0 x 0002%.
3. The alignment value of the third variable C is 2, so the valid alignment value is 2, which is stored in the order of 0x0006 and 0 x 0006% 2 = 0.
Therefore, from 0x0000 to 0x00007, stexample variables are stored in a total of eight-character nodes. Because the alignment value of stexample is 4, the valid alignment value of stexample is 2. Again 8% 2 = 0, stexample only occupies eight bytes from 0x0000 to 0x0007. So sizeof (struct stexample) = 8.
//////////////////////////////////////// //////////////////////////////////////
The nested structure of struct is similar to alignment.
See the following example:
Struct stexample <br/>{< br/> char a; <br/> struct B <br/>{< br/> char AA; <br/> short BB; <br/> int cc; <br/>}< br/> short C; <br/> }; <br/> // <br/> sizeof (struct stexample) = 16
The Byte alignment in the memory is shown in:
The alignment value of the struct B struct is 4 (determined by the member CC), so the storage address must be an integer multiple of 4.
The self-alignment value of the struct stexample struct is also 4 (determined by the struct B Member), so the last two bytes are used for completing (namely, 0x000e and 0x0010 ).
//////////////////////////////////////// ////////////////////////////////////////
The Byte alignment of the Union shared body is similar. The alignment value of the shared body depends on the maximum alignment value of the member.
//////////////////////////////////////// ////////////////////////////////////////
Byte alignment. Generally, you do not need to worry about writing upper-layer applications.
However, there are two situations where you need to be especially careful. One is the Hardware Memory Operation and the other is the network packet transmission.
When a struct is defined for a network packet, non-alignment of bytes may cause a big mistake. There are two solutions:
1. Pack (1) can be declared as 1-byte alignment. However, the operation efficiency will decrease, and the compiler support of some embedded systems is not good enough.
2. The member variables in the network packet structure can be defined with the short type at the maximum. The char type can be used, but the even bytes must be aligned. (The standard network packet structure is an even number of bytes aligned ). When int type variables are required, you can define a small shared body typedef Union {char cmem [] 4; short smem [2]} union_int; it is used to replace int in the message structure, but it is enough to be noticed in the program.