Using disassembly method to study the structure of C language:
#include <stdio.h>intMainintargcChar**argv) { struct { CharA; Shortb; intC; CharD; } s; S.A.=1; s.b=2; S.C=3; S.D=4; printf ("%u\n",sizeof(s)); return 0; }
The disassembly results of several statements in the main function are as follows:
As you can see from the instructions that access the members of the struct, the four members of the struct are arranged like this on the stack:
Although the stack is growing from a high address to a low address, struct members are also arranged from low addresses to high addresses, which are similar to arrays. Unlike arrays, a struct member is not a close-to-one arrangement, there is a gap in the middle, called a fill (Padding), and not only that, it also has a three-byte padding at the end of the struct, so the value of sizeof (s) is 12. The%u conversion instructions for printf represent unsigned numbers, and sizeof's value is siez_t type, which is some kind of unsigned shaping.
Why does the compiler handle this? Most computer architectures are limited to instructions for accessing memory, and on 32-bit platforms, access to 4-byte instructions (such as movl above) should be an integer multiple of 4, and the memory address accessed by two-byte instructions (such as the above MOVW) should be an integer multiple of two bytes. This is called alignment (Alignment). What happens if the memory address that the instruction accesses is not aligned correctly? On some platforms will not be able to access the memory, but to throw an exception, on the x86 platform is still able to access the memory, but the alignment of instruction execution efficiency is lower than the alignment of instructions, so the compiler to arrange the address of the various variables will take into account the alignment problem. For the struct in this example, the compiler aligns its base site to a 4-byte boundary, meaning that the ebp-0x10 address must be an integer multiple of 4. S.A. takes one byte and has no alignment issues. s.b occupies two bytes, and if S.B is close to S.A., its address cannot be an integer multiple of two bytes, so the compiler inserts a padding byte into the struct. The address of the s.b is also an integer multiple of two bytes. S.C accounted for 4 bytes, close to the back of s.b, because ebp-0xc this address is also an integer multiple of 4. So why should there be padding in the back of the S.D to the 4-byte boundary? This is to make it easier to arrange the address of the variable behind the struct, adding an array of this struct type, so that the latter struct can be arranged next to the previous structure to ensure that its base address is still aligned to the 4-byte boundary, because the padding byte is already at the end of the previous struct. Reasonable design of the structure of the members of the order can save storage space, such as the above example structure can be changed to the following:
struct { char A; Char D; Short b; int C;} s;
In addition, GCC provides an extended syntax to eliminate the padding bytes in the struct:
struct { char A; Short b; int C; Char D; } __ATTRIBUTE__ ((packed)) s;
This makes it impossible to ensure that struct members are aligned and that there may be an efficiency problem when accessing B and C.
Previously we used data types that accounted for a few bytes, the smallest type also accounted for one byte, and in the struct you could use the bit field syntax to define only a few bit members.
#include <stdio.h>typedefstruct{unsignedintOne1; unsignedintBoth:3; unsignedintThree:Ten; unsignedintFour5; unsignedint:2; unsignedintFive8; unsignedintSix8;} Demo_type;intMainvoid) {Demo_type s= {1,5,513, -,129,0x81 }; printf ("sizeof Demo_type =%u\n",sizeof(Demo_type)); printf ("values:s=%u,%u,%u,%u,%u,%u\n", S.one, S.two, S.three,s.four, s.five, s.six); return 0;}
The layout of the s structure is as follows:
A Bit field member can be of type int or unsigned int, representing a signed or unsigned number, but does not mean that it stands 4 bytes like a normal int, the number behind it is a few bits, or it can be like a unsigned int : 2 This defines an unnamed bit field, even if the unnamed bit field is not written, it is possible for the compiler to insert a fill bit between two members, such as between five and six, so that the six member is just a single byte, and the access efficiency will be higher. The end of the struct is also populated with 3 bytes to align to the 4-byte boundary. The byte order of x86 is small, as can be seen from the order of one and two, if a byte is subdivided, the bit order in the byte is also small, because the member that is in front of the struct (a member near the lower address side) takes the low in bytes. Bit field is useful in drivers because it is often necessary to manipulate one or a few bits in the device register separately.
[Compilation and C-language relations] 4. Structures and unions