Some think about SIZEOF ()
Majianan
This is a post on the Internet, and I have never remembered there, but I think it is very good. I added some content in the back of the article, which is about the class of SIZEOF. If there is any mistake, please correct it, thank you ~~ --- Majianan 2005-12-19 I have added the original article to supplement, add some of the SIZEOF of String and references. - Majianan 2006-1-6
0. Type: sizeof, byte alignment, type size
Sizeof, a guy who is unstoppable, causing countless rookies, is stunned. Xiaoba, I didn't have a confused committee, adhering to the great thoughts of "hard me, happiness,", I decided to summarize it in detail. But when I summed it, I found that this problem can be easily and complicated. So the place in this article is not suitable for beginners, and even there is no need to master a masterpiece. But if you want to "know it, better", then this article can help you. The rookie I have not been in-depth for C , including mistakes, welcome to correct! 1. Definition: Where is SIZEOF? SizeOf is an operator in C / C is also. Simply speaking, its role is to return an object or type of memory byte 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 compiler Lin Lin is always in total, but as a norm, they will guarantee the sizeof value of char, souded char and unsigned char, after all, char is our programming The minimum data type for use. 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 their SIZEOF values. Here, the object can further extend to an expression, ie, SIZEOF can be evaluated to an expression. The compiler determines the size according to the final result type of the expression, and does not calculate the expression. For example: sizeof (2); // 2 type 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 (Double); SIZEO can also call a function call, the result is the size of the function returns the type, and the function will not be called.
Let's take a complete example: ************************************************** *************** CHAR FOO () {Printf ("Foo () HAS been Called./N"); return 'a';} int main () {// foo The return value type is char // so SZ = sizeof (char), but the function foo () will not be called SIZE_T SZ = SizeOf (Foo ()); Printf ("SizeOf (" SizeOf (")) =% D / N ", SZ);} *************************************************** ************** C99 Standards, functions, unable to determine the type of expression and bit-field members cannot be calculated, 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); // error 3. The calculation of the constant SizeOf of SizeOf occurs at the 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 the program below can perform correctly in 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 pass in a compiler that does not fully implement the C99 standard, 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. The basic data type of the basic data type here refers to the simple built-in data type of short, int, long, float, double. Because they are related to the system, the value may be different under different systems. This must cause our attention, try not to make trouble to the transplantation of our program in this regard. In general, in the 32-bit compilation environment, the value of SIZEOF (int) is 4. 5. String's sizeOf a String size is independent of the length of the string it points to. For different STLs, the structural definition of the String class will vary, so different tools, such as VC , and .NET, the result will be different, on my machine, the results in VC 6.0 are 16 ,. The run results in Net2003 are 28.
But for the same compiler, its results are certain. String ST1 ("blog.sina.com.cn"); string ST2 ("Majianan"); string st3; string * ps = & st1; cout << "ST1: << SIZEOF (ST1) << endl; cout <<" St2: "<< Sizeof (ST2) << endl; cout <<" st3: " 7. When the referenced SIZEOF SIZEOF operator is applied to the reference type, the return is the memory length required to include the reference object (that is, the size of the reference object) cout << "Short: / t" << Sizeof (SHORT << Endl; cout << "short *: / t" << sizeof (short *) << Endl; cout << "short &: / t" << Sizeof (Short &) << Endl; Cout << "Short [4]: / t "<< SIZEOF (Short [4]) << Endl; cout <<" INT &: / T "<< SizeOf (int & << Endl; output results: short: 2short *: 4short &: 2Short [4]: 8INT &: 4 8. 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, and there is a NULL terminator SIZEOF (A2) at the end of the character; / / The result is 3 * 4 = 12 (dependent INT) Some friends have just started SIZEOF as a number of set elements, now You should know that this is wrong. So how should you ask the number of array elements? Easy, usually there are two ways: int C1 = sizeof (a1) / sizeof (char); // Total length / single element length INT C2 = SizeOf (A1) / SizeOf (A1 [0]); // Total The length of the first element is written here, will mention one, the following C3, the C4 value should be? *********************************************************** ******* 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, C3 has been recognized, yes, C3! = 3. Here the function parameter A3 is no longer an array type, but it turns into a pointer. It is equivalent to Char * A3, why don't think about it carefully? When we call the function foo1, the program assigns an array of size 3 on the stack? will not! The array is "in-service", the caller only needs to pass the address of the arguments, so A3 is naturally a pointer type (char *), and the value of C3 is 4. 9. Structural Sizeof This is a problem that beginners asking the most, so there is a need for a lot of ink. Let us first look at a structure: struct s1 {char c; int i;}; ask SIZEOF (S1)? Smart, you start thinking, Char accounts for 1 byte, Int accounts for 4 bytes, then add up should be 5. Is that right? Have you tried it on 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 am I always the one who's hurt? Please don't be frustrated, let's take a good idea of SIZEOF - SIZEOF's results equal to the number of memory bytes of the object or type. Ok, let's take a look at the memory allocation of S1: s1 = {'a', 0xfffffffff}; after defining the above variables, add breakpoints, run the program, observe the memory in S1, you found it what? Taking my VC6.0 as an example, the address of S1 is 0x0012FF78. The data is as follows: 0012ff78: 61 CC CC CC FF FF FF found? How to mix 3 bytes of CC in the middle? Take a look at the description of MSDN: when applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment. This is the legendary byte! An important topic appeared. Why do you need a byte alignment? Computer composition principles teach us, which helps accelerate the number of speeds of your computer, 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 complete. In this class, this, 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 in S1: Struct S2 {Int i; char C;}; How is the result of SIZEOF (S2)? Why is it still 8. Look at memory, there is still three filling bytes behind the member C. Why is this? 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 top guidelines, there are a few things to explain: 1) The front is not the address of the structure of the structure is the integer of its size, how can it say that the offset is? Because there is a 1st point, we can only consider the offset of members, so thinking about it. 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 Built-in data type like char, short, int, float, double. The "data width" mentioned here 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 of members, and the broad and simple type of S3 is int. Thus, the number of stall defined by S3 is required to be 4, and the value of the entire SIZEOF (S3) should also be 4. Is the offset of C1 of 0 and S? At this time, S is a whole, which also satisfies the three criters in front of the structural variable, so it is 8, the offset is 4, and the C1 and S need three filling bytes, and C2 and S are It is not required, so the offset of C2 is 12, and the size of C2 is 13, 13 is not 4, which is still added to three filling bytes at the end. 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 10. The sizeof value of the class SizeOf class is equal to the number of memory byouts occupied by member variables in the class. Such as: ************************************************ *************** Class a {public: int b; float c; char d;}; int main (void) {a object; cout << "Sizeof (Object) IS "<< sizeof (object) << Endl; return 0;} ******************************************* ************************* The output result is 12 (the sizeof (float) value on my machine is 4, the byte has been speaking ).