The reason for byte alignment
To increase the storage speed of the CPU, the compiler optimizes the storage of the struct and union, which is byte-aligned.
Alignment
For structs or unions in a struct or union, their byte alignment standard is the number of bytes of data with the largest number of bytes in all its members.
In general, the number of bytes used by C + + variables
Char:1 bytes;
Short:2 bytes;
Int:4 bytes;
Long:4 bytes;
Long Long:8 bytes;
Float:4 bytes;
Double:8 bytes;
Bool:1 bytes;
The conditions to be met for byte alignment in *struct:
1. The offset of a variable's starting position relative to the starting position of the structure is an integer multiple of the byte number of the variable;
2. The total number of bytes occupied by the structure is an integer multiple of the number of bytes of the variable with the longest number of bytes in the struct.
Cases:
1 struct Struct 2 {3 Double D1; 4 Char D2; 5 int D3; 6 }a;
sizeof (a) = 8 + 1 + 3 + 4 = 16. The 3 bytes that are made up are an integer multiple of 4 for the starting position of the int data relative to the start position of the structure.
1 struct Struct 2 {3 Char D1; 4 Double D2; 5 int D3; 6 }b;
sizeof (b) = 1 + 7 + 8 + 4 = 20. 20/8 = 2 ... 4, so we need to make up 4 bytes, making it an integer multiple of 8.
Two conditions to be met for byte alignment in *union:
1, the size of the unoin must be sufficient to accommodate the widest members;
2. The size of the Union needs to be divisible by the size of the underlying member type it contains.
Another way to align bytes
VC provides #pragma pack (n) to customize byte alignment
There are two situations:
1, n is greater than the number of bytes of the variable: The offset only satisfies the default byte alignment;
2, n is less than the number of bytes of the variable: The offset is an integer multiple of n and does not use the default byte alignment.
Cases:
1 #pragmaPack (push)//Keep the alignment state2 #pragmaPack (4)//set to 4-byte alignment3 structTest4 {5 CharM1;6 Doublem2;7 intm3;8 }a;9 #pragmaPack (POP)//Restoring the Alignment stateTen sizeof(a) =1+3+8+4= - //The three-bit is because N is less than 8, so the starting position of the M2 is N, or 4, relative to the start position of the structure. One A - #pragmaPack (8) - structS1 the { - CharA; - Longb; - }; + structS2 - { + CharC; A structS1 D; at Long Longe; - }; - #pragmaPack () - - sizeof(S1) =1+3+4=8 - sizeof(S2) =1+3+8+4+8= -。//The addition of 4 is because the byte number of the variable E is 8, and its offset from the starting position must be a multiple of 8.
The discussion of the byte alignment problem has ended on the top. Here are some examples of the two topics I have come across:
1.
1#include <stdio.h>2 Union3 {4 Charx[5];5 inti;6 }a;7 8 intMain ()9 {Tena.x[0] =Ten; Onea.x[1] =1; Aprintf"%d\n", A.I); -printf"%d\n",sizeof(a)); - return 0; the}
Output is 266 8
Analytical:
Allocating memory to the union involves byte-alignment issues, which are described in more detail here, and are simply explained here. The memory allocated by Union must be a multiple of all the base data types in the Union.
In this topic, which is a multiple of 1 and 4, and Char x[5] occupies 5 bytes, the size of the memory allocated by the Union should be 8 bytes.
The high-byte in the Windows system is after the low byte in front. Char X[5] has only the first two values, that is, two values are only 2 bytes, that is, the int data in the union is only low two bits on the value.
The binary representation of I is:
00000000 00000000 00000001 00001010
i.e.: 2^1 + 2^3 + 2^8 = 266
Also equivalent to 16 binary 0x010a, i.e.: 10 * 16^0 + 1 * 16^2 = 266
Here to add the conversion problem, also I collected:
Binary conversion
Decimal |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Hexadecimal |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
Binary |
0000 |
0001 |
0010 |
0011 |
0100 |
0101 |
0110 |
0111 |
1000 |
1001 |
1010 |
1011 |
1100 |
1101 |
1110 |
1111 |
hexadecimal digits convert decimal digits:
0x2af5 Convert decimal:
5 * 16^0 = 5
F * 16^1 = 240
A * 16^2 = 2560
2 * 16^3 = 8192
---------------
5 + 240 + 2560 + 8192 = 10997
decimal digits convert hexadecimal digits:
2500 Convert Hex:
2500/16 = 156 ... 4
156/16 = 9 ... (C)
9/16 = 0 ... 9
----------------------
Get 4c9, reverse 9c4, that is, 2500 hexadecimal representation is: 0X9C4
Binary numbers convert hex digits:
101110011011.1001
Take the Si he method, that is, the binary decimal point is the dividing point, to the left (or right) every four bits.
After the component is good, the binary and hexadecimal number of the corresponding table, the four-bit binary by the right to add, the number is a hexadecimal number, and then in order, the position of the decimal point is unchanged.
The result is: b9b.9
It is important to note that when you take four bits to the left (or to the right), the highest bit (the lowest bit) is not able to make up four bits, you can fill the leftmost (or rightmost) of the decimal point by 0 to convert.
Hexadecimal numbers convert binary numbers:
The binary and hexadecimal number of the corresponding table, the hexadecimal number is divided into binary numbers, with four-bit binary numbers by the right to add, and finally get binary digits, the decimal point is still.
2.
1#include <iostream>2 using namespacestd;3 4typedefstructA5 {6 CharAchar;7 intaint_2;8 ShortaInt;9 }typea;Ten OnetypedefstructB A { - Charbchar[3]; - TypeA BA; the Doublebdouble; - }typeb; - - intMain () + { - TypeA A; + TypeB B; Acout <<sizeof(a) << Endl <<sizeof(b) <<Endl; at return 0; -}
Output is 12 24
Analytical:
The answer to this question can easily be drawn from the discussion of the above byte alignment problem.
sizeof (TYPEA) = 1 + 3 + 4 + 2 = 10. 10/4 = 2 ... 2, it is necessary to fill 2 bytes, that is, sizeof (TYPEA) = 12;
sizeof (TYPEB) = 3 + 1 + 12 + 8 = 24. The 1 bytes are made up because the default alignment of the TypeA type in the struct TYPEB
is 4 bytes (that is, the byte size of int, which is the longest byte in the struct TypeA).
A careful discussion of C + + byte alignment issues