Sizeof, byte alignment, multi-inheritance, virtual inheritance, member function pointer

Source: Internet
Author: User

Keywords: sizeof, byte alignment, multi-inheritance, virtual inheritance, member function pointer

Forward Declaration:

Sizeof, a handsome guy, leads countless cainiao to fold his waist. I didn't make too many mistakes at the beginning, sticking to"
I decided to give a detailed summary of the great idea of working hard for ten million people.
However, when I sum up, I find that this problem can be both simple and complex.
It is suitable for beginners and does not even have to write a masterpiece. But if you want to "know the truth, know the truth,
This article may be helpful to you.
I have not learned much about C ++ in cainiao, but I have many errors. please correct me.

1. Definition:
Where is sizeof? The Holy sizeof is an operator in C/C ++.
Return the memory bytes occupied by an object or type.
The description on msdn is as follows:
The sizeof keyword gives the amount of storage, in bytes, associated with
Variable or a type (including aggregate types ).
This keyword returns a value of Type size_t.
The return value type is size_t, which is defined in the header file stddef. h. This is a value dependent on the compilation system.
Is defined
Typedef unsigned int size_t;
Compilers in the world are widely used, but as a specification, they all guarantee char, signed Char, and unsigned
The sizeof value of char is 1. After all, char is the smallest data type that can be programmed.
2. Syntax:
Sizeof has three syntax forms:
1) sizeof (object); // sizeof (object );
2) sizeof (type_name); // sizeof (type );
3) sizeof object; // sizeof object;
So,
Int I;
Sizeof (I); // OK
Sizeof I; // OK
Sizeof (INT); // OK
Sizeof int; // Error
Since writing 3 can be replaced by writing 1, in order to unify forms and reduce the burden on our brains, there are 3rd writing methods, forget
Drop it!
In fact, the size of the sizeof computing object is also converted to the calculation of the object type, that is, the same type
The sizeof values of different objects are consistent. Here, the object can be further extended to the expression, that is, sizeof can
Evaluate an expression. The Compiler determines the size based on the final result type of the expression.
. For example:
Sizeof (2); // The type of 2 is int, so it is equivalent to sizeof (INT );
Sizeof (2 + 3.14); // The type of 3.14 is double, and 2 is also upgraded to double, so it is equivalent
In sizeof (double );
Sizeof can also be used to evaluate a function call. The result is the size of the function return type, and the function is not called.
Let's take a complete example:
Char Foo ()
{
Printf ("Foo () has been called./N ");
Return 'a ';
}
Int main ()
{
Size_t SZ = sizeof (FOO (); // the return value type of Foo () is Char, so SZ = sizeof (
Char), Foo () is not called
Printf ("sizeof (FOO () = % d/N", SZ );
}
According to the c99 standard, functions, expressions of undetermined types, and bit-field members cannot be computed by S.
Izeof value, that is, the following statements are incorrect:
Sizeof (FOO); // Error
Void foo2 (){}
Sizeof (foo2 (); // Error
Struct s
{
Unsigned int F1: 1;
Unsigned int F2: 5;
Unsigned int F3: 12;
};
Sizeof (S. F1); // Error
3. constants of sizeof
The sizeof calculation occurs at the Compilation Time, so it can be used as a constant expression, such:
Char ary [sizeof (INT) * 10]; // OK
The latest c99 standard stipulates that sizeof can also be calculated at runtime. The following programs can be used in Dev-C ++.
Correct execution:
Int N;
N = 10; // n Dynamic assignment
Char ary [N]; // c99 also supports dynamic definition of Arrays
Printf ("% d/N", sizeof (ary); // OK. Output 10
But it won't work in the compiler that does not fully implement the c99 standard, and the above Code won't be able to compile in vc6.
Therefore, we 'd better think that sizeof is executed during the compilation period, so as not to cause errors, so that the program can be transplanted.
Strong.
4. sizeof of basic data type
The basic data types here refer to simple built-in data types such as short, Int, long, float, and double,
Because they are all related to the system, the values may be different in different systems, which must cause our attention.
Do not bother porting your program in this aspect.
Generally, in a 32-bit compiling environment, the value of sizeof (INT) is 4.
5. sizeof pointer variable
If you have learned the data structure, you should know that the pointer is a very important concept, which records the address of another object. Both
If the address is stored, it is equal to the width of the address bus in the computer. So in a 32-bit computer
The return value of a pointer variable must be 4 (note that the result is in bytes). It can be predicted that, in the next 6
The sizeof result of the four-bit pointer variable is 8.
Char * Pc = "ABC ";
Int * PI;
String * pS;
Char ** PPC = & PC;
Void (* PF) (); // function pointer
Sizeof (PC); // The result is 4
Sizeof (PI); // The result is 4
Sizeof (PS); // The result is 4
Sizeof (PPC); // The result is 4
Sizeof (PF); // The result is 4
The sizeof value of the pointer variable has no relationship with the object indicated by the pointer. It is precisely because all pointer variables occupy
The storage size is equal, so the MFC message processing function uses two parameters wparam and lparam to transmit various complex consumption
Information Structure (using a pointer to the struct ).
6. sizeof of Array
The sizeof value of the array is equal to the number of memory bytes occupied by the array, for example:
Char A1 [] = "ABC ";
Int A2 [3];
Sizeof (A1); // The result is 4. A null Terminator exists at the end of the character.
Sizeof (A2); // The result is 3*4 = 12 (dependent on INT)
Some friends regard sizeof as the number of elements in the array at the beginning. Now, you should know that this is incorrect,
How to calculate the number of array elements is easy. there are usually two ways to write:
Int C1 = sizeof (A1)/sizeof (char); // total length/length of a single element
Int C2 = sizeof (A1)/sizeof (A1 [0]); // total length/length of the first element
Write it here and ask, what is the value of C3 and C4 below?
Void foo3 (char A3 [3])
{
Int C3 = sizeof (A3); // C3 =
}
Void foo4 (char A4 [])
{
Int C4 = sizeof (A4); // C4 =
}
Maybe when you try to answer the C4 value, you realize that C3 is wrong. Yes, C3! = 3. Here the function parameter A3 is no longer
Again, the array type is converted into a pointer, which is equivalent to char * A3. Why do you think about it?
When we call the function foo1, will the program allocate an array of 3 on the stack? No! The array is "transferred"
The caller only needs to pass the real parameter address, so A3 is a pointer type (char *), and the value of C3 is
4.
7. sizeof of struct
This is the most frequently asked question for beginners, so it is necessary to pay more attention here. Let's first look at a struct.
:
Struct S1
{
Char C;
Int I;
};
Ask how smart the sizeof (S1) is. You start to think about it. Char occupies 1 byte and INT occupies 4 byte.
The sum is 5. Is that true? Have you tried it on your machine? Maybe you are right, but you are probably wrong.
Of! In vc6, the default value is 8.
Why is my injury always me?
Don't be frustrated. Let's take a look at the definition of sizeof. The result of sizeof is equal to the object or type.
The number of memory bytes occupied. Well, let's take a look at the memory allocation of S1:
S1 S1 = {'A', 0 xffffffff };
After defining the above variables, add breakpoints, run the program, and observe the memory where S1 is located. what do you find?
Take my vc6.0 as an example. The S1 address is 0x0012ff78, and its data content is as follows:
0012ff78: 61 CC FF
What are the three-byte CC 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 siz
E, which may include Padding Bytes 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 computer data acquisition? No
It takes more time to execute the command cycle. Therefore, the compiler will process the struct by default (in fact, the number
According to the variable), so that the basic data type (short, etc.) with the width of 2 is located on the address that can be divisible by 2,
Let the basic data type (such as INT) with a width of 4 be located on the address that can be divisible by 4, and so on. In this way, two
In the middle of the number, you may need to add the padding byte, so the sizeof value of the entire struct increases.
Let's exchange the positions of char and INT in S1:
Struct S2
{
Int I;
Char C;
};
Check the result of sizeof (S2). Why 8? Then check the memory. The original member C still has three fields.
Byte filling. Why? Don't worry. The following summarizes the rules.

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 padding byte (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
The last member is added with the padding byte (trailing padding ).
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. Why do I mention the offset?
So we can only consider the member offset, which 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 obtained through the macro offsetof ().
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 equals 4
2) The basic type refers to the built-in data types such as char, short, Int, float, and double.
The "data width" here refers to the size of its sizeof. The struct can be a composite member.
For example, another struct, so when looking for the widest basic type member, it should include the child of the composite type member
Members, rather than the composite Members as a whole. However, when determining the offset position of a composite member
Composite type 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
Vc6 is used as an example. I will not describe it later ):
Struct S3
{
Char C1;
S1 S;
Char C2
};
The type of the widest and simplest member in S1 is int. When S3 considers the widest and simplest type member, it "disconnects" S1,
So S3's simplest and widest type is int. In this way, the first address of its bucket needs to be rounded up to four for variables defined by S3.
In addition, the entire sizeof (S3) value should also be divided by 4.
The offset of C1 is 0, and the offset of S is a whole. As a struct variable, S satisfies the first three
Standard, so the size is 8, the offset is 4, and three bytes are required between C1 and S, and there is no need between C2 and S.
So the offset of C2 is 12, so the C2 size is 13, and 13 cannot be divisible by 4.
The last three padding bytes. 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 have a new understanding of the sizeof struct, but don't be too happy.
An important parameter that affects sizeof is the pack instruction of the compiler. It is used to adjust the structure
Body Alignment mode. Different compiler names and usages are slightly different. In vc6, # pragma pack is used for implementation.
Directly modify the/ZP compilation switch. # Basic usage of The Pragma Pack: # pragma pack (N), where N is byte aligned
Number. The value is 1, 2, 4, 8, and 16. The default value is 8. If this value is smaller than the sizeof value of the struct
The offset of the member should take this value as the standard, that is, 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, plus sizeof (I)
Equal to 6, can be divided 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 offset of sizeof (C2) is 9
Split by 2 and add a padding 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 a "no"
How can the space occupied variables be distinguished by the address and two different "Empty struct" variables?
The "null struct" variable must also be stored, so that the compiler can only allocate one byte of space to it
Bit. As follows:
Struct S5 {};
Sizeof (S5); // The result is 1.

8. sizeof containing bitfield struct
As mentioned above, bitfield members cannot be taken sizeof values independently. Here we will discuss the structure of a bitfield.
The sizeof of is specifically listed in consideration of its particularity.
C99 specifies that int, unsigned int, and bool can be bit domain types, but almost all compilers have extended this,
Other types are allowed.
The main purpose of bit domains is to compress storage. The general rules are as follows:
1) if the type of the adjacent bit field is the same and the sum of its bit width is smaller than the sizeof size of the type
Segments are stored next to the previous field until they cannot be accommodated;
2) If the field type of the adjacent bit field is the same, but the sum of its bit width is greater than the sizeof size of the type
The offset from the new storage unit is an integer multiple of its type;
3) if the types of adjacent bitfield fields are different, the implementations of each compiler are different.
Type, Dev-C ++ adopts the compression method;
4) do not compress fields that are interspersed with non-bit fields;
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
{
Char F1: 3;
Char F2: 4;
Char F3: 5;
};
Its memory layout is:
| _ F1 __|__ F2 __| _ | ____ F3 ___ | ____ |
| _ |
0 3 7 8 1316
The bit field type is Char, and the 1st bytes can only accommodate F1 and F2, so F2 is compressed to 1st bytes, while F3 only
Starting from the next byte. Therefore, the result of sizeof (bf1) is 2.
Example 2:
Struct bf2
{
Char F1: 3;
Short F2: 4;
Char F3: 5;
};
Because the adjacent bit fields have different types, in vc6, sizeof is 6, and in Dev-C ++ is 2.
Example 3:
Struct bf3
{
Char F1: 3;
Char F2;
Char F3: 5;
};
The non-bit field is interspersed in it and will not produce compression. The size obtained in vc6 and Dev-C ++ is 3.
9. sizeof of the Consortium
The struct structure is sequential in the memory organization, while the consortium is overlapping. Each member shares a memory segment, so the entire
The sizeof of a consortium is the maximum value of sizeof each member. The struct member can also be a composite type.
Composite Members are considered as a whole.
Therefore, in the following example, the sizeof value of U is equal to sizeof (s ).
Union u
{
Int I;
Char C;
S1 S;
};

 

From http://www.cnitblog.com/wuzhimeili/archive/2006/08/15/15308.html

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.