Structure byte alignment
When we use the sizeof operator to calculate the space occupied by a struct, we do not simply add the space occupied by all elements in the struct. This involves the issue of memory byte alignment. Theoretically, access to any variable can start from any address, but in fact it is not. In fact, access to a specific type of variable can only be accessed at a specific address, in this case, variables need to be arranged according to certain rules in space rather than simply in order. This is memory alignment.
Reason for memory alignment:
1) Some platforms can only access specific types of data at specific addresses;
2) improve the speed of data access. For example, some platforms read data from even addresses each time. For an int-type variable, if it is stored in an even address unit, the variable can be read in only one read period; however, if the variable is stored in an odd address unit, two read cycles are required to read the variable.
Alignment policy of Microsoft C compiler on Win32 platform:
1) The first address of the struct variable can be divisible by the size of its widest data type member. When the compiler opens up space for struct variables, it first finds the widest data type in the struct, and then finds the location where the memory address can be divisible by the size of the data type, this position is the first address of the struct variable. The size of the widest data type is used as the alignment standard.
2) The offset (offset) of each member relative to the first address of the struct is an integer multiple of the size of each member. If necessary, bytes are filled between the members. When the compiler opens a blank space for a struct member, it first checks whether the offset of the address of the preopened space relative to the first address of the struct is an integer multiple of the size of the Member. If so, it stores the member; if not, fill in several bytes to obtain an integer multiple.
3) the space occupied by struct variables must be an integer multiple of the widest data type. If necessary, several bytes will be filled at the end of the last Member to make the occupied space an integer multiple of the widest data type.
Next, let's take a look at how sizeof calculates the struct size.
1. test1 empty struct
Then sizeof (S) = 1; or sizeof (S) = 0;
C ++ occupies 1 byte, while C occupies 0 byte.
2. Test2
typedef struct node1{ int a; char b; short c;}S1; |
Then sizeof (S1) = 8. This is because the longest data type in node1 is int, which occupies 4 bytes. Therefore, if it is 4 bytes aligned, the structure is stored in the memory as follows:
| -------- Int -------- | 4 bytes
| Char | ---- | -- short-| 4 bytes
8 bytes in total
3. test3
typedef struct node2{ char a; int b; short c;}S2; |
Siezof (S3) = 12. The maximum data type is int, which occupies 4 bytes. Therefore, it is 4-byte alignment, and its storage in the memory space is as follows:
| Char | ---- | 4 bytes
| -------- Int -------- | 4 bytes
| -- Short -- | ---- | 4 bytes
12 bytes in total
4. test4 contains static data members
typedef struct node3{ int a; short b; static int c;}S3; |
Then sizeof (S3) = 8. here, the struct contains static data members, and the storage location of static data members is irrelevant to the storage address of the struct instance (note that only the struct in C ++ can contain static data members, in C, the struct cannot contain static data members ). The memory storage method is as follows:
| -------- Int -------- | 4 bytes
| -- Short-| ---- | 4 bytes
The variable C is stored in the static data zone separately. Therefore, siezof is used to calculate the space occupied by C in an hour.
5. The test5 struct contains the struct.
typedef struct node4{ bool a; S1 s1; short b;}S4; |
Then sizeof (S4) = 16. Because S1 occupies 8 bytes, and S1 has the longest data type of int, which occupies 4 bytes. bool has 1 byte, and short occupies 2 bytes. Therefore, it is aligned with 4 bytes, the storage method is
| ------- Bool -------- | 4 bytes
| ------- S1 ---------- | 8 bytes
| ------- Short ------- | 4 bytes
6. test6
typedef struct node5{ bool a; S1 s1; double b; int c;}S5; |
Then sizeof (S5) = 32. The reason is that S1 occupies 8 bytes, while S1 occupies 4 bytes of the longest data type, while double occupies 8 bytes. Therefore, if it is 8 bytes aligned, the storage mode is as follows:
| -------- Bool -------- | 8 bytes
| --------- S1 --------- | 8 bytes
| -------- Double ------ | 8 bytes
| ---- Int ---- | --------- | 8 bytes
7. test7
If the # pragma pack (n) command is used in the program to force N-byte alignment, n is 8 by default.
Then compare the byte size of N and the longest data type in the struct, and take one of the smaller values as the alignment standard.
If you want to cancel the forced alignment, run the # pragma pack () command ()
If the command # pragma pack (4) is used at the beginning of the program
typedef struct node5{ bool a; S1 s1; double b; int c;}S5; |
Sizeof (S5) = 24. Because it is forced to be 4 bytes aligned, and the longest data type in S5 is double, which occupies 8 bytes, It is 4 bytes aligned. The memory storage method is as follows:
| ----------- A -------- | 4 bytes
| -------- S1 ---------- | 4 bytes
| -------- S1 ---------- | 4 bytes
| -------- B ----------- | 4 bytes
| -------- B ----------- | 4 bytes
| --------- C ---------- | 4 bytes
To sum up, pay attention to the following points when calculating sizeof:
1) if the struct is empty, only one byte is occupied.
2) If all data types in the struct are the same, the occupied space is the length of the member data type × number of members.
If the data types in the struct are different, take the space occupied by the longest data type members as alignment criteria. If the data member contains another struct variable t, the longest data type in T is compared with other data members, and the longest data type is used as the alignment standard. However, t is stored as a unit and only needs to be read by other Members.
3) if the # pragma pack (n) command is used to force the alignment standard, the smaller of the N and the maximum number of bytes of the struct are used as alignment standards.
In addition to alignment in the struct, common variable storage also has the situation of byte alignment, that is, Self alignment. The compiler stipulates that the first storage address of a common variable must be divisible by the data type width of the variable.
Test procedure:
?
/* Test the sizeof operator 2011.10.1 */
#include <iostream>
using
namespace
std;
// # Pragma pack (4) // set the 4-byte alignment
// # Pragma pack () // cancel the 4-byte alignment
typedef
struct
node
{
}S;
typedef
struct
node1
{
int
a;
char
b;
short
c;
}S1;
typedef
struct
node2
{
char
a;
int
b;
short
c;
}S2;
typedef
struct
node3
{
int
a;
short
b;
static
int
c;
}S3;
typedef
struct
node4
{
bool
a;
S1 s1;
short
b;
}S4;
typedef
struct
node5
{
bool
a;
S1 s1;
double
b;
int
c;
}S5;
int
main(
int
argc,
char
*argv[])
{
cout<<
sizeof
(
char
)<<
" "
<<
sizeof
(
short
)<<
" "
<<
sizeof
(
int
)<<
" "
<<
sizeof
(
float
)<<
" "
<<
sizeof
(
double
)<<endl;
S s;
S1 s1;
S2 s2;
S3 s3;
S4 s4;
S5 s5;
cout<<
sizeof
(S3)<<endl;
cout<<
sizeof
(s)<<
" "
<<
sizeof
(s1)<<
" "
<<
sizeof
(s2)<<
" "
<<
sizeof
(s3)<<
" "
<<
sizeof
(s4)<<
" "
<<
sizeof
(s5)<<endl;
return
0;
}
Structure byte alignment