(Zz from http://www.gridchina.org/~wfsun/blog/archives/000658.html)
SizeOF ------------------------------------- -------------------------------------------------- -----
Keywords: sizeof, byte alignment, multi-inheritance, virtual inheritance, member function pointer
Forward statement: SizeOf, a guy who is unstoppable, caught countless rookie, the shrimp, I didn't have a relaxation, and I made a great idea of "hard me, a happy thousands of people", I decided to put it as much as possible Summary. But when I summed it, I found that this problem can be easier and complicated, so there is not suitable for beginners, and even there is no need to master. But if you want to "know it, better", then this article can help you. The rookie I haven't worry about C , there is no shortage of mistakes, welcome you to correct
1. Definition: SIZEOF is a holy sizeOf is a operator in C / C is also, simply saying that its role is to return an object or type of memory by the number of memory bytes. Explanation on MSDN is: The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types) This keyword returns a value of type size_t its return type size_t, in the header file. Stddef.h is defined. This is a value dependent on the compilation system. It is generally defined as TypeDef unsigned int size_t; the world's compiler Lin Lin's total, but as a norm, they will guarantee the sizeof value of char, souded char and unsignedchar. After all, char is our programming Minimum data type. 2. Syntax: SizeOf has three grammar forms, as follows: 1) sizeof (object); // sizeof (object); 2) sizeof (type_name); // sizeof (type); 3) sizeof object; // sizeof object; So, int i; sizeof (i); // oksizeof i; // oksizeof (int); // OksizeOf int; // error Since the writing 3 can be used to write method 1, in order to unify the form, the burden of our brain, The third type of writing, forget it! In fact, the size of the SIZEOF calculation object is also converted to the type of object type, that is, the same type of different objects have a SIZEOF value. Here, the object can further extend to the expression, ie, SizeOf can be evaluated to an expression, the compiler determines the size according to the final result type of the expression, generally does not calculate the expression.
Such as: sizeof (2); // 2 is int, so equivalent to SizeOf (int); SIZEOF (2 3.14); // 3.14 Type of Double, 2 will also be upgraded into Double type, so wait Price from sizeof (doubleof) can also call a function call, the result is the size of the function returns the type, the function will not be called, let's take a complete example: char foo () {Printf ("foo () HAS Been Called./N "); Return 'a';} int main () {size_t SZ = sizeof (foo ()); // foo () return value type is char, so SZ = SIZEOF (charr ), Foo () does not call Printf ("SizeOf (Foo ()) =% D / N", SZ);} C99 standard specified, function, unable to determine the type of expression and bit domain (Bit-Field) Members cannot be calculated by the sizeof value, that is, the following writes are wrong: 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); // error3. SIZEOF's constant SIZEOF's calculation occurs at compilation time, so it can be used as a constant expression, such as: char Ary [SIZEOF (INT) * 10]; // OK latest C99 standard specification SIZEOF can also be calculated at runtime, as follows: int N = 10; // n below DEV-C : int N = 10; // n Dynamic assignment Char Ary [n]; // c99 also supports the dynamic definition of arrays Printf ("% d / n", sizeof (ary)); // ok. Output 10 but does not fully implement the C99 standard compiler No, the above code is not compiled in VC6. So we'd better think SIZEOF is executed in the compile period, which will not cause errors to make the program's portability. 4. SIZEOF SIZEOF here's basic data type refers to Simple built-in data types such as short, int, long, float, double, because they are all associated with the system, so at different systems may be different, this Be sure to attract us, try not to make trouble to your own programs in this regard. In general, in the 32-bit compilation environment, the value of sizeof (int) is 4.5. You should know the pointer is a very important concept, which records the address of another object. . Since it is to store the address, it is of course equal to the width of the internal address bus of the computer. So in the 32-bit computer, the return value of a pointer variable must be 4 (note that the result is in bytes), which can be expected that the sizeOf result of the pointer variable in the future 64-bit system is 8.
Char * pc = "abc"; int * pi; string * ps; char ** PPC = & pc; void (* pf) (); // function pointer SIZEOF (PC); / / result is 4SizeOf (pi); / / Result is 4SizeOf (PS); / / The result is 4SizeOf (PPC); / / result is 4SizeOf (PF); / / The result is that the SizeOF value of the 4 pointer variable is not any relationship with the object refers to the pointer, it is because of all The pointer variables are equal to the memory size, so the MFC message processing function uses two parameters WPARAM, LPARAM to deliver a variety of complex message structures (using pointers to the structure). 6. The sizeOf value of the array SIZEOF array is equal to the number of memory bytes occupied by the array, such as: char A1 [] = "abc"; int A2 [3]; sizeof (a1); / / result is 4, the character end There is a NULL terminator SIZEOF (A2); / / resulting 3 * 4 = 12 (dependent INT) Some friends have just started SIZEOF as a number of group elements, now you should know this is wrong So how should you ask an array element? Easy, usually there are two ways: int C1 = sizeof (a1) / sizeof (char); // Total length / single element length INT C2 = SizeOf (A1) / SIZEOF (A1 [0]); // The length of the total length / The first element is written here, and the following question, the following C3, the C4 value should be how much 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 value of C4, it is aware of C3 answer. , Yes, C3! = 3. Here the function parameter A3 is no longer an array type, but it turns into a pointer, which is equivalent to Char * A3. Why don't you think about it? When we call the function foo1, the program will assign a size of 3 in the stack. Will not! The array is "in-service", the caller only needs to pass the address of the arguments, so A3 naturally is a pointer type (char *), the value of C3 is 4.7. Structural Sizeof This is an initiator asked One of the most questions, so there is a need for a lot of pen ink. Let's take a structure: struct s1 {char c; int i;}; ask SIZEOF (S1) equal to how much smart, you start thinking, Char accounts for 1 byte, int 4 byte, then add up It should be 5. Is this? Are you tried over your machine? Maybe you are right, but it is very likely that you are wrong! The result of the default setting is 8 in VC6.
Why why should I be injured, please don't be frustrated, let's take a look at the SizeOf's result is equal to the number of internal memory byte, ok, let's take a look at S1 memory allocation. Situation: S1 S1 = {'A', 0xfffffffff}; After defining the above variables, add breakpoints, run the program, observe the memory of S1, you found what is the address of my VC6.0, S1 address is 0x0012FF78, the data content is as follows: 0012ff78: 61 CC CC CC FF FF Ff found what is found in the middle inclusions 3 bytes of CCs to see the description of the MSDN: When Applied to a structure Type or variable, sizeof returns the actual Size, Which May include Padding bytes Inserted for alignment. This is this is the legendary byte! An important topic appeared. Why do you need a byte alignment computer composition principle to teach us to help speed up the computer's number of speeds, otherwise it will have a multi-flowering command cycle. To this end, the compiler will process the structure by default (this is also the data variable in other parts, so that the basic data type (Short, SHORT, etc.) capable of being able to be completely removed, so that the width is 4 The basic data type (INT, etc.) are located on an address that can be 4 completely, and push it. Thus, the middle of the two numbers may need to add a padding byte, so the sizeof value of the entire structure increases. Let us exchange the position of CHAR and int I; struct s2 {int I; char c;}; look at the result of SizeOf (S2), how is it still 8, then look at memory, there is still three behind members c Fill bytes, this is why don't worry, summarize the law. The detail of byte alignment and compiler implementation, but in general, the three guidelines are met: 1) The first address of the structural variable can be removed by the size of its widest basic type member; 2) Each member of the structure is relatively The offset of the structural header address is an integer multiple of the member size. If a compiler is needed, the compiler will add a fill byte (INTERNAL ADDING); 3) The total size of the structure is structured. The widest and basic type member size is integrated, if a compiler is required to add a fill byte after the last member. For the above guidelines, there are several needs: 1) The front is not the address of the structure of the structure is an integer multiple of its size, how to say the offset is because there is a 1 point, so we can only Think about the offset of the member, thinking is simple. Think about why.
The offset of a member of a member relative to the structure of the structure can be obtained by macro OFFSTOF (), which is also defined in stddef.h, as follows: #define offsetof (s, m) (SIZE_T) & (((SIZE_T) & (S *) 0) -> M) For example, if you want 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 means the previous mentioned A built-in data type like char, short, int, float, double, "Data Width" herein refers to the size of its sizeOf. Since members of the structure can be a composite type, such as another structure, it should include sub-members of the composite type member when looking for the widest basic type member, rather than regarding composite members as a whole. However, when determining the offset position of the composite type member, the composite type is treated as an overall. It is a bit 拗拗 here, thinking about a little scratching, or let us look at the example (the specific value is still vc6 as an example, will no longer explain): struct s3 {char C1; S1 S; char C2;}; s1 The widest and simple member is int, S3 is considering the broadcase type member, so the broad and simple type of S3 is int, so that the variable defined by S3, its storage space first The address needs to be 4, and the value of the entire SIZEOF (S3) should also be divided by 4. The offset of C1 is 0. The offset of S is a whole, which also satisfies the three criters as the structural variable, so it is 8, the offset is 4, C1 and S are between C1 and S. There is a need for 3 filling bytes, while C2 and s are not needed, so the offset of C2 is 12, and the size of C2 is 13, 13 is not 4, which is still added to the end. 3 filled bytes. Finally, the value of SIZEOF (S3) is 16. Through the above description, we can get a formula: the size of the structure is equal to the offset of the last member plus the size of the size plus the number of padded bytes, namely: sizeof (struct) = offsetof (Last Item) SizeOf (Last Item) Sizeof (Trailing Padding)
Here, friends should have a new understanding of SizeOf, but don't be too early, there is an important parameter that affects SizeOf has not been mentioned, which is the Pack instruction of the compiler. It is used to adjust the structure alignment, and different compiler names and use methods are slightly different. VC6 can be implemented by #pragma pack, or the / zp compilation switch can also be modified. #Pragma Pack's basic usage is: #pragma pack (n), n is the number of bytes, with a value of 1, 2, 4, 8, 16, the default is 8, if this value is a SIZEOF value of the structure Small, then the offset of the member should be subject to this value, ie, the offset of structural members should take the minimum value of the two, the formula is as follows: Offsetof (item) = min (n, sizeof )) Re-see example: #pragma pack (push) // Set the current Pack Set the stack to save #pragma pack (2) // must use Struct S1 {char C; INT I;}; Struct S3 {before the structural definition CHAR C1; S1 S; CHAR C2;}; # PRAGMA PACK (POP) // Restore previous Pack settings When calculation SIZEOF (S1), the value of min (2, sizeof (i)) is 2, so I's offset The amount is 2, plus SIZEOF (I) is equal to 6, can be divided by 2, so the size of the entire S1 is 6. Similarly, for the offset of SizeOf (S3), S is 2, the offset of C2 is 8, plus SIZEOF (C2) equal to 9, can not be removed, add a padding byte, SIZEOF (S3) is equal to 10. Now, friends can easily take a breather, :) Other note, "empty structure" (excluding data member) is not 0, but 1. Imagine a "unexpected space" variable to take the address, how is the two different "empty structural" variables to distinguish, so "empty structure" variables have to be stored, so the compiler can only be It assigns a space for one byte for placement. As follows: Struct S5 {}; sizeof (S5); / / The result is 18. SizeOf of the content domain structure has said that the bit domain member cannot be taken separately, and we will discuss it here is a bit field. SIZEOF's SIZEOF just taking into account its particularity, it is specifically columnnated. C99 specifies that int, unsigned int and bool can be used as a bit domain type, but the compiler extends almost all, allowing other types of types. The main purpose of the bit domain is to compress storage, and its approximate rules are: 1) If the type of neighbor domain field is the same, its bit width is smaller than the type of SizeOf size, the following fields will close adjacent to the previous field storage, Until until it does not accommodate; 2) If the type of neighbor domain field is the same, its bit width and larger than the type of SIZEOF size, the following field will start from the new memory cell, its offset is an integer of its type size Double; 3) If the type of adjacent bit field fields are different, the specific implementation of each compiler is different. VC6 takes no compression mode, DEV-C takes a compression method; 4) If the bit domain field is inserted into non-position The domain field is not compressed; 5) The total size of the entire structure is an integer multiple of the widest basic type member size.