Detailed description of C/C ++ struct byte alignment

Source: Internet
Author: User

Original article: http://blog.csdn.net/hyljqr/article/details/500899

StructSizeof
First look at a struct:
Struct S1
{
Char C;
Int I;
};

the default value of sizeof (S1) in vc6 is 8.
Let's first look at the definition of sizeof -- the result of sizeof is equal to the number of memory bytes occupied by the object or type. Okay, let's take a look at the memory allocation of S1
S1 S1 = {'A', 0 xffffffff};
after defining the above variable, add the breakpoint, run the Program and observe the memory where S1 is located. What did you find?
take my vc6.0 (SP6) as an example, the S1 address is 0x0012ff78, and its data content is as follows:
0012ff78: 61 cc ff
I found out why CC with 3 bytes is mixed in the middle. Let's take a look at the description on msdn:
when applied to a structure type or variable, sizeof returns the actual size, which may include padding byte S inserted for alignment.
originally, this is the legendary byte alignment! An important topic has emerged.
Why Do We Need byte alignment principles to teach us how to speed up the computer's data acquisition speed? Otherwise, it will take a much longer command cycle. For this reason, the compiler will process the struct by default (in fact, the data variables in other places are also the same), so that the basic data type with a width of 2 (short, etc) are located on the address that can be divisible by 2, so that the basic data type (INT, etc.) with the width of 4 is located on the address that can be divisible by 4, and so on. In this way, the two numbers may need to be added to the padding byte, so the sizeof value of the entire struct increases.
let's switch the positions of char and INT in S1:
struct S2
{< br> int I;
char C;
};
check the number of sizeof (S2) results. Why 8? Check the memory again. The original member C still has three padding bytes, this is why. Don't worry. Let's summarize the rules below.

The details of byte alignment are related to compiler implementation, but generally three criteria are met:
1) The first address of the struct variable can be divisible by the size of its widest basic type member;
2) The offset (offset) of each member of the struct to the first address of the struct is an integer multiple of the member size. If necessary, the compiler will add the internal adding between the members );
3) the total size of the struct is an integer multiple of the size of the widest basic type of the struct. If necessary, the compiler will add the trailing padding after the last member ).
There are several notes for the above principles:
1) I didn't mean that the address of a struct member is an integer multiple of its size. How can I talk about the offset? Because a 1st point exists, we can only consider the member offset, this is easy to think about. Think about why.

The offset of a member of the struct to the first address of the struct can be macro The macro is also defined in stddef. H, as follows:
# Define offsetof (S, m) (size_t) & (S *) 0)-> m)
For example, to get the offset of C in S2, the method is size_t Pos = offsetof (S2, c); // POS is equal to 4
2) The basic type refers to the built-in data types such as char, short, Int, float, and double mentioned above. The "data width" here refers to the size of its sizeof. Because the struct member can be a composite type, for example, another struct, when looking for the widest basic type member, it should include the Child Member of the composite type member, instead of seeing a composite member as a whole. However, when determining the offset of a composite member, the composite type is regarded as a whole. This is a bit difficult to describe here, and it seems a bit confusing to think about it. Let's take a look at the example (the specific value is still taken as an example of vc6 and will not be explained later ):
Struct S3
{
Char C1;
S1 S;
Char C2
};
The type of the widest and simplest member of S1 is int. When considering the widest and simplest type members, S3 splits S1, so the widest and simplest type of S3 is int. In this way, for variables defined by S3, the first address of the bucket needs to be divisible by four, and the entire sizeof (S3) value should also be divisible by four. The offset of C1 is 0, and the offset of S is a whole. As a struct variable, S satisfies the preceding three criteria, so its size is 8 and its offset is 4, three bytes are required between C1 and S, and the offset between C2 and S is 12, the size of C2 is 13, and 13 cannot be fully divided by 4. Therefore, three fill bytes must be added at the end. Finally, the value of sizeof (S3) is 16.
Through the above description, we can get a formula:
The size of the struct is equal to the offset of the last member plus the size of the struct plus the number of filled bytes at the end, that is:

Sizeof (struct) = offsetof (last item) + sizeof (tr
Ailing padding)

Here, friends should Sizeof has a new understanding, but don't be too happy, there is an important parameter that affects sizeof has not been mentioned, that is, the pack command of the compiler. It is used to adjust the structure alignment mode. Different compiler names and usages are slightly different. In vc6, the # pragma pack is used for implementation, and you can also directly modify the/ZP compilation switch. # Basic usage of The Pragma Pack: # pragma pack (N), where N is the number of bytes alignment. The default value is 8, if this value is smaller than the sizeof value of the struct member, the offset of the struct member should take the minimum value of the two. The formula is as follows:
Offsetof (item) = min (n, sizeof (item ))
Let's look at the example:
# Pragma pack (push) // Save the current pack setting pressure Stack
# Pragma pack (2) // must be used before struct Definition
Struct S1
{
Char C;
Int I;
};
Struct S3
{
Char C1;
S1 S;
Char C2
};
# Pragma pack (POP) // restore previous pack settings
When sizeof (S1) is calculated, the value of min (2, sizeof (I) is 2, so the offset of I is 2, and the value of sizeof (I) is 6, it can be divisible by 2, so the size of the entire S1 is 6. Similarly, for sizeof (S3), the offset of S is 2, the offset of C2 is 8, and the addition of sizeof (C2) is equal to 9, cannot be divisible by 2, add a fill byte, so sizeof (S3) is equal to 10.
Now, friends can breathe a sigh of relief ,:)
Note that the size of the "Empty struct" (excluding data members) is not 0, but 1. Imagine how a variable with "no space occupied" can be separated by an address and two different "Empty struct" variables. Therefore, the variable "Empty struct" must also be stored, in this way, the compiler can only allocate one byte of space for occupying space. As follows:
Struct S5 {};
Sizeof (S5); // The result is 1.

sizeof with a bit domain struct :
As mentioned earlier, a bit domain member cannot be taken sizeof value separately, what we will discuss here is the sizeof of struct containing bit fields, which is specifically listed considering its particularity.
c99 specifies that int, unsigned int, and bool can be bit domain types, but almost all compilers have extended this type to allow the existence of other types.
the main purpose of bit domains is to compress storage. The general rule is as follows:
1) if the fields of adjacent bit domains are of the same type, and the sum of its bit width is smaller than the sizeof size of the type, the subsequent word
segment will be stored next to the previous field until it cannot be accommodated;
2) if the types of adjacent bit fields are the same, but the sum of Bit Width is greater than the sizeof size of the type, the subsequent word
starts from the new storage unit, its offset is an integer multiple of its type.
3) if the types of adjacent bit field are different, the implementations of each compiler are different, vc6 adopts the
type, and Dev-C ++ adopts the compression mode.
4) if the bit field is interspersed with non-bit field,
5) the total size of the entire struct is an integer multiple of the size of the widest basic type.

let's take a look at the example.
Example 1:
struct bf1
{< br> char F1: 3;
char F2: 4;
char F3: 5;
};
the memory layout is:
|__ F1 ___ | ____ F2 ___ |__ | ____ F3 ______ |
|__ |__ | __|__ |__ |
the bit field type is Char, the 1st bytes can only accommodate F1 and F2, so F2 is compressed to 1st bytes, while F3 only
can start from the next byte. Therefore, the result of sizeof (bf1) is 2.
Example 2:
struct bf2
{< br> char F1: 3;
short F2: 4;
char F3: 5;
};
In vc6, sizeof is 6 and it is 2 in Dev-C ++ because the adjacent bit fields have different types.
Example 3:
struct bf3
{< br> char F1: 3;
char F2;
char F3: 5;
};
the non-bit field is interspersed with the field, and no compression is generated. The size obtained in vc6 and Dev-C ++ is 3.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.