http://blog.csdn.net/xing_hao/article/details/6678048
One. Memory alignment
Many computer systems restrict the location of basic types of data in memory, and they require that the value of the first address of the data be a multiple of a number k (usually 4 or 8), which is called memory alignment, and this k is called the Zimo number of the data type (alignment modulus). When the ratio of one type S pair of Zimo number to the Zimo number of another type T is an integer greater than 1, we call the alignment requirement of type S stronger (strict) than T, while the T is weaker than s (loose). This mandatory requirement simplifies the design of the transfer system between the processor and the memory and improves the speed of reading the data. For example, such a processor, every time read and write memory from a certain 8 times times the address of the beginning, read out or write 8 bytes of data, if the software can guarantee that the double type of data from 8 times times the address of the beginning, then read or write a double type of data only need a memory operation. Otherwise, we might need two memory operations to complete this action, because the data might just be across two 8-byte blocks of memory that meet the alignment requirements. Some processors can make an error if the data does not meet the alignment requirements, but Intel's IA32 architecture processor works correctly regardless of whether the data is aligned. But Intel advises that if you want to improve performance, all the program data should be aligned as much as possible.
The
ANSI C standard does not stipulate that adjacent declared variables must be contiguous in memory. For program efficiency, memory alignment issues are handled flexibly by the compiler, which can result in some padding bytes between adjacent variables. For the base data type (int char), the memory space they occupy has a definite value under a certain hardware system, so we'll just consider the memory allocation of the struct member.
win32 platform:
1) The first address of a struct variable can be divisible by the size of its widest base type member;
Note: When the compiler opens up space for the struct, it first finds the widest base data type in the struct, and then looks for the location where the memory address can be divisible by the base data type as the first address of the struct. The size of the widest base data type as described above for the Zimo number.
2) the offset (offset) of each member relative to the first address of the struct is an integer multiple of the member size, and if necessary, the compiler adds padding bytes between the members (internal adding);
Note: Before creating space for a member of a struct, the compiler first checks that the first address of the pre-open space is an integer multiple of this member relative to the first address of the struct, if it holds this member, and vice versa, fills a certain number of bytes between this member and the previous member. In order to achieve an integer multiple of the requirements, that is, the pre-opening space of the first address after the move a few bytes.
In the GNU GCC compiler, there are some differences in the guidelines, and the Zimo number is not determined by the widest base data type, as described above.
In GCC, the Zimo number rule is: The maximum number of Zimo is only 4, that is, even if there is a double type in the structure, the number of Zimo or 4, so the Zimo number can only be 1,2,4. And in the above three, in 2nd, offset must be an integer multiple of the member size, if the member size is less than or equal to 4 according to the above criteria, but if greater than 4, The offset (offset) of each member of the struct relative to the first address of the struct can only be judged by the integer multiples of 4 to add padding.
See the following example:
structT
{
Char ch;
Double D ;
};
Then, under GCC, sizeof (T) should be equal to 12 bytes.
If the struct contains bit fields (Bit-field), then the guidelines in VC have to be changed:
1) if the type of the adjacent bit field field is the same, and its bit width is less than the type sizeof size, The subsequent fields will be stored next to the previous field until they are not accommodated;
2) If the adjacent bit field field is of the same type, but its bit width is greater than the type sizeof size, then the subsequent field will start from the new storage unit, and its offset is an integer multiple of its type size;
3) If the type of the adjacent bit field fields is different, the specific implementation of the compiler differs, VC6 takes an uncompressed approach (different bit field fields are stored in different bit field type bytes), and dev-c++ and GCC are compressed;
Note: When two field types are not the same, For non-compression methods, for example:
structN
{
Char C:2;
int i:4;
};
Still to meet the non-domain structure in the body of the alignment criteria 2nd, I member relative to the first address of the structure of the offset should be 4 integer times, so the C member to fill 3 bytes, and then open 4 bytes of space as an int, 4 bits to hold I, so the above structure in the VC occupies a space of 8 bytes , and for compilers that use compression, follow the rule 2nd, which does not contain a bit-domain structure, if the 3-byte padding can hold the bits of the next member, it is compressed into the padding byte and cannot accommodate the space, so the upper struct n is in gcc or dev-c++ The space occupied by this should be 4 bytes.
4) If the bit field fields are interspersed with non-bit field fields, they are not compressed;
Note:
struct 5) the total size of the entire struct is an integer multiple of the size of the widest base type member.
typedefstruct
{
Char C:2;
Double i;
int c2:4;
}N3;
The space occupied by GCC is 16 bytes, and the space occupied by VC should be 24 bytes.
Ps:
- The selection of the Zimo number can only be based on the basic data type, so for nested structures in structs, only the underlying data types that are split are considered. For the 2nd of the alignment criterion, the whole structure is considered as a member, and the size of the member is judged by the alignment criterion according to the structure body.
- Class objects are stored in memory in a similar manner to the structure, and are no longer described here. It should be noted that the size of the class object only includes the space occupied by non-static member variables in the class, and if there is a virtual function, then add another pointer to the space occupied.
1. Memory alignment is related to compiler settings, first of all to understand the compiler this default value is how much
2. If you do not want the compiler to default, you can specify the N-aligned by #pragma pack (n)
3. Each struct variable is aligned, if the alignment parameter n (compiler default or specified by pragma) is greater than the number of bytes (m) of the variable, then the memory offset address is a multiple of m according to M alignment, otherwise the address in the memory offset is a multiple of n. Which is the minimum length rule.
4. struct Size: The length of the alignment must be an integer multiple of the largest alignment parameter in the member. The maximum alignment parameter is obtained from the third step.
5. Add: If struct B is also in structure A, then the alignment of B is to select the alignment of the longest member in it
Two. Bit field
While some information is stored, it does not need to occupy a full byte, only a few or one bits. For example, when storing a switching volume, there are only 0 and 12 states, with one binary. In order to save storage space and make processing simple, C language also provides a data structure, called "bit field" or "bit segment". The so-called "bit field" is to divide the binary in one byte into several different regions and describe the number of bits per region. Each domain has a domain name that allows operations to be performed by domain name in the program. This allows you to represent several different objects in a bits field of one byte. The definition of a bit field and the description of a bit-field variable are similar to the structure definition, in the form of:
struct bit domain structure name
{bit field List};
Where the list of bit fields is in the form: type specifier bit domain name: bit field length
For example:
struct BS
{
int a:8;
int b:2;
int c:6;
};
The description of a bit-field variable is the same as the structure variable description. Can be defined by the first description, at the same time define the description or direct description of the three ways. For example:
struct BS
{
int a:8;
int b:2;
int c:6;
}data;
Indicates that data is a BS variable, which accounts for two bytes. Where bit domain A occupies 8 bits, bit domain B is 2 bits, bit field C is 6 bits. There are several explanations for the definition of bit fields:
1. A bit field must be stored in the same byte and cannot span two bytes. If one byte has enough space left to hold another domain, the bit field should be stored from the next cell. You can also intentionally make a field start from the next unit. For example:
struct BS
{
unsigned a:4
unsigned:0/* airspace */
Unsigned b:4/* Start storage from the next unit */
unsigned c:4
}
In this bit domain definition, a occupies the first byte of 4 bits, the latter 4 bits fill 0 means not to use, B starts with the second byte, occupies 4 bits, and C occupies 4 bits.
2. Because bit fields are not allowed to span two bytes, the length of the bit field cannot be greater than the length of one byte, that is, it cannot exceed the 8-bit binary.
3. A bit field can have no bit domain name, it is only used to fill or adjust the location. Nameless bit fields are not available. For example:
struct k
{
int a:1
Int:2/* The 2-bit cannot be used */
int B:3
int C:2
};
From the above analysis, we can see that the bit field is essentially a type of structure, but its members are assigned by binary.
Three. Use of bit fields
The use of bit fields is the same as the use of struct members, in the general form of bit domain variable name • Bit domain name field allows output in various formats.
Main () {
struct BS
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
Bit.a=1;
bit.b=7;
bit.c=15;
printf ("%d,%d,%d/n", bit.a,bit.b,bit.c);
pbit=&bit;
pbit->a=0;
pbit->b&=3;
pbit->c|=1;
printf ("%d,%d,%d/n", pbit->a,pbit->b,pbit->c);
}
In the example program, the bit-domain structure BS is defined, and the three-bit domain is a,b,c. The variable bit for the BS type and pointer variable pbit to the BS type are described. This means that a bit field can also use pointers.
The 9, 10, and 113 lines of the program assign values to the three bit fields respectively. (Note that the assignment cannot exceed the allowed range of this bit field) the 12th line of the program outputs the contents of three fields in an integer format. The 13th line sends the address of bit field variable bit to pointer variable pbit. The 14th row assigns a value to bit field A as a pointer to 0. Line 15th uses the compound bitwise operator "&=", which is equivalent to: pbit->b=pbit->b&3 bit field B has a value of 7, and 3 for bitwise AND operation results of 3 (111&011=011, decimal value 3). Similarly, the 16th line of the program uses the compound bit operation "|=", equivalent to: pbit->c=pbit->c|1 its result is 15. The 17th line of the program outputs the values of these three fields in a pointer manner.
The memory alignment problem and bit field of C-language structure