The conquer of the tricky problem of C/C + + sizeof

Source: Internet
Author: User

Today, when programming, simply use the following procedure to find the number of elements in a vector container:

vector<int> vec;  for (int0; i++) {    vec.push_back (i);} int sizeof sizeof (int);

The program runs as a result of size=4 (sizeof (VEC) =16,sizeof (int) =4) instead of size=100. This surprised me, so I went through the following experiment:

vector<int> vec_int;vector<char> vec_char;vector<double > vec_double; int sizeof (vec_int); int sizeof (Vec_char); int sizeof (vec_double);

The values for Size_vec_int, Size_vec_char, and size_vec_double are found to be 16. This shows that all three of them ask for only the vector type size.

The number of elements in the vector can be requested in the following ways:

vector<int> vec; int size = vec.size ();

Links reproduced below: Click to open

Summary:

sizeof's role is simple: to find the size of an object or type. However, sizeof is very complex, it involves a lot of special circumstances, this article to classify these situations, summed up the 10 characteristics of sizeof:

(0) sizeof is an operator, not a function;

(1) sizeof cannot obtain the length of void type;

(2) sizeof can obtain the length of the pointer of void type;

(3) sizeof can obtain the length of the array of statically allocated memory!

(4) sizeof cannot calculate the size of dynamically allocated memory!

(5) sizeof cannot find the length of an incomplete array;

(6) When an expression is an operand of sizeof, it returns the type size of the expression's computed result, but it does not evaluate the expression!

(7) sizeof can size the function call, and the size obtained is equal to the size of the return type, but does not execute the function body!

(8) The size of the struct (and its objects) calculated by sizeof does not equal the size of each data member Object!

(9) sizeof cannot be used to find the size of a member of a struct, but the size of a struct containing a bit-field member can be obtained!

Overview:

sizeof is a key word in C + + that is an operator that takes the length of an object ( data type or data Object ) (that is, the size of the memory, in bytes ). Where types contain basic data types (excluding void), user-defined types (structs, classes), function types . A data object is an ordinary variable and a pointer variable (containing a void pointer) defined with the previously mentioned type. The size of the different types of data differs in different platforms, but the C standard specifies that sizeof (char) equals 1 for all build platforms. For more overview of sizeof you can always enter sizeof on MSDN for queries.

Look at the above, perhaps you see not much feeling. Okay, here's a list of the many features of sizeof that are causing sizeof to be a more tricky keyword:

Top Ten Features: attribute 0:sizeof is an operator, not a function

This feature is the most basic characteristic of sizeof, and many of the features behind it are affected by this feature, because sizeof is not a function, so we do not call the length of the object it is called parameters, I am accustomed to called the operand (this is not rigorous, but helps me remember that sizeof is an operator).

attribute 1:sizeof cannot obtain length of type void

Yes, you cannot use sizeof (void), which will cause a compilation error: illegalsizeof operand. In fact, you cannot declare a variable of type void, and if you do not believe you try void A; The compiler will also error: illegal use of type ' void '. Perhaps you have to ask why, very good, learn things can not only know it, but also know why. We know that an important function of declaring variables is to tell the compiler how much storage space the variable requires. However, void is an "empty type" and what is an empty type, which you can understand as a type that does not know the size of the storage space. Since the compiler cannot determine the storage size of a variable of type void, it naturally does not allow you to declare such a variable. Of course, it is possible to declare a pointer of type void! This is the content of feature 2.

attribute 2:sizeof can obtain the length of a pointer of type void

As stated in attribute 1, you can declare a pointer of type void, which means that the compiler can determine the storage space occupied by a pointer of type void. In fact, this is true, at present, almost all versions of the compiler on all platforms see the size of the pointer as 4byte, do not believe you try sizeof (int*), sizeof (void*), sizeof (double*), sizeof (person*), and so on, They're all equal to 4! Why is it? Well asked, I will do my best to explain this: the pointer is also a variable , but this variable is very special, it is the address of the other variables to store the variable. And because the current 32-bit computer platform of the program section of the addressing range is 4GB, addressing the minimum unit is BYTE,4GB equals 232Byte, so much memory its address if encoded, only need to use 32 bit on the line, and 32bit = 32/8 = 4byte, This means that only 4byte will be able to store these memory addresses. So the sizeof operation of any type of pointer variable results in a 4!

The 3:sizeof attribute is able to calculate the length of an array of statically allocated memory!

int a[10]; int n = sizeof (a); if sizeof (int) equals 4, then n= 10*4=40; Special note: charch[]= "abc"; sizeof (ch); The result is 4, note that the end of the string array is ' \ n '! In general, we can use sizeof to calculate the number of elements contained in an array, with the following method: int n = sizeof (a)/sizeof (a[0]);

It is very important to note that the use of sizeof in the form parameter group of a function. For example, assume the following function:

void Fun (int array[    ]) {intsizeof(array);}

What do you think is the value of N in fun? If you answer 40, then I regret to tell you that you are wrong again. Here n equals 4, in fact, regardless of whether the formal parameter is an array of type int, or a float array, or any other array of user-defined types, and no matter how many elements the array contains, n is 4! Why is it? The reason is that when the function parameter is passed, the array is converted to a pointer, perhaps you want to ask why to translate into pointers, for reasons can be found in many books, I simply say: If the whole array is passed directly, then it is necessary to involve the copy of the array element (the actual parameter to the copy of the formal parameter), This can result in very inefficient function execution! Instead of just passing the address of the array (that is, the pointer), you only need to copy 4byte.

attribute 4:sizeof cannot calculate the size of dynamically allocated memory!

If you have the following statement: int*a = new Int[10];int n = sizeof (a); What is the value of n? Is it 40? The answer is NO! In fact, N equals 4, because A is a pointer, as described in Feature 2: Under 32-bit platforms, all pointers are of 4byte! size. Remember, a in this case is not the same as the A in feature 3! Many people (even some teachers) think that the array name is the pointer, in fact, there are many differences between the two, to know the details, please see "c Expert programming." With attributes 3 and 4, we see that arrays and pointers are inextricably related, and these relationships are also a major factor in the potential error of the program, and I'll explain the relationship between pointers and arrays in detail in the conquer of thepointers and arrays of the tricky questions of C + + .

Attribute 3 indicates that sizeof can calculate the size of a statically allocated array, while feature 4 illustrates the size of dynamically allocated memory that sizeof cannot find. So some people think that sizeof is compile-time evaluation, and give reasons: statement int array[sizeof (int) *10]; can be compiled through, and many books have said that the array size is compiled to determine, since the previous statement can be compiled, So it is considered that sizeof is evaluated at compile time. After further testing I found this conclusion somewhat arbitrary! At least some of them are not rigorous! Because a dynamic array can be defined in a compiler that implements the C99 standard (such as dev C + +), that is: statement: int num;cin>>num; int Arrary[num]; is right (note that it is wrong in vc6.0). So I'm going to use the statement int n=sizeof (array) in dev C + + for the array, the Cout<<n<<endl to size, the result to compile, the runtime to enter Num's value of 10, and the output n equals 40! It is obvious here that Num's value is entered at run time, so sizeof cannot get the size of the array at compile time! So that sizeof becomes a runtime evaluation.

So is sizeof a compile-time evaluation or a run-time evaluation? The initially C standard stipulates that sizeof can only be evaluated at compile time, and later C99 adds that sizeof may be evaluated at runtime. However, it is worth noting that even in Dev C + +, which implements the C99 standard, it is still not possible to use sizeof to calculate the size of dynamically allocated memory!

attribute 5:sizeof cannot find the length of an incomplete array!

Before we elaborate on this feature, we assume that there are two source files: File1.cpp and File2.cpp, where File1.cpp has the following definitions:

intarraya[Ten] = {1,2,3,4,5,6,7,8,9,Ten};intarrayb[Ten] = { One, A, -, -, the, -, -, -, +, -};

The file2.cpp contains the following statements:

externarraya[];externarrayb[];cout<<sizeof(Arraya) <<endl;            // compilation Error!! cout<<sizeof(ARRAYB) <<endl;

In File2.cpp, the third statement compiles an error, and the first statement is correct, and can output 40! Why is it? The reason is that sizeof (Arraya) tries to find the size of an incomplete array. The incomplete array here is an array of exponential group sizes that are not determined! The function of the sizeof operator is to find the size of an object, but the declaration: extern int arraya[] Just tells the compiler that Arraya is an integer array, but does not tell the compiler how many elements it contains. So for sizeof in file2.cpp it cannot find the size of Arraya, so the compiler simply does not let you compile.

Then why does sizeof (ARRAYB) Get arraryb size? The key is to explicitly tell the compiler arrayb[10 is an integer array of 10 elements, using Externint Arrayb when declared in File2.cpp. The size is therefore deterministic.

The explanation of this feature is almost over. In fact, this problem can also be derived from the connection and compilation of knowledge points, but at present I do not have the confidence of these two knowledge points for detailed, thorough explanation, so inconvenience in this swim, in the near future I will add related issues in this series of elaboration.

attribute 6: When an expression is an operand of sizeof, it returns the type size of the expression's computed result, but it does not evaluate the expression!

To illustrate this problem, let's look at the following program statements:

Char 1 ; int num=1; int n1 =sizeof(ch+num); int sizeof (ch =ch+num);

Assuming that Char occupies 1byte,int occupies 4byte, then what is the value of n1,n2,ch after executing the above program? I believe a lot of people will think that N1 and N2 are equal, and many people think that CH equals 2, the fact that these people are wrong. In fact N1 equals 4,n2 equals 1,ch equals 1, for what? Please look at the analysis:

Because of the default type conversion, the type of the expression ch+num evaluates to int, so the value of N1 is 4! The type of the result of the expression Ch=ch+num is char, remembering that although the result is an int when the ch+num is computed, the type conversion occurs when the result is assigned to CH, so the final type of the expression is char, so N2 equals 1. The N1,N2 values are 4 and 1, respectively, because sizeof returns the type size of the expression evaluation, not the type size of the variable that occupies the largest memory in the expression!

For N2=sizeof (Ch=ch+num), at first glance the program seems to implement the function of having CH plus num assigned to CH, which is not true! Because sizeof only cares about the type size, it naturally should not evaluate the expression, otherwise it would be superfluous. It is precisely because of this, here to warn you, try not to be in sizeof directly to the size of the expression, in order to avoid errors, you can be sizeof (ch = ch+num), modified to write ch = ch +num;sizeof (CH); Although one more statement, seemingly redundant, In fact, a lot of benefits: first more clear, second will not appear 1 such errors (assuming the logic of the program itself is to execute ch = ch +num;).

The 7:sizeof attribute can be sized for a function call, and the size of the obtained is equal to the size of the return type, but the function body is not executed!

Suppose you have the following function (it is a poorly written function, but it is a good indication of the problem that needs to be addressed):

int Fun (int& num,constint& Inc) {         float2.0 ;          double ret =0;          = num+Inc;          = num/div;          return ret;}

Then the statement:

int 3 ; int 5 ; cout<<sizeof(fun (b)) <<endl;cout<<a<<endl;

How much does it output? Different people will give different answers, and I'll discuss the value of sizeof (A, b) and the value of a, respectively:

First, the value of sizeof (A, b) is 4, because when you use sizeof to size a function call, it gets the size of the return type of the function, and the return type of fun (A, B) is int,sizeof (int) equals 4. Many people confuse the return type of a function with the type of the return value , thinking that the value of sizeof (A, b) is 8 because the function return value is RET, and RET is defined as double,sizeof (doube) equals 8. Note that although the function return value type is double, when the function returns, the value is cast as a type (the conversion is unsafe here). Others mistakenly think that the value of sizeof (A, B) is 12, and that the reason for that is: Fun internally defines two local variables, one is a float, one is double, and sizeof (float) +sizeof (doube) = 4+8=12. The answer seems reasonable, but they mistakenly think that sizeof here is looking at the size of the variable inside the function. Of course it's wrong.

Next look at the value of a: The correct answer is 3! Do you remember feature 6? Very similar here, sizeof's operand is a function call, it does not execute the function body! For this reason, it is recommended that you do not put the function body in parentheses behind the sizeof, so that it is easy to mistake the function of the execution, in fact, it did not execute.

Since the use of sizeof for a function bar is the size of the return type of a function, it is natural to conclude that you cannot use sizeof to size a function that returns a type void! Please refer to feature 1 for reasons. Similarly, a function call that returns a type that is any type of pointer uses sizeof to obtain a size of 4, so refer to feature 2.

Finally, let's take a look at this statement: cout<<sizeof (fun); How much is the answer? In fact, it does not get the answer, because the compilation will not pass! At first, I thought I could output answer 4, because I think fun is the function name, and I know the function name is the address of the function, the address is the pointer, so I think that sizeof (fun) is actually a pointer to size, according to the characteristics of 2, any pointer size is 4. But when I went to verify, the compiler didn't let me pass! What is this for? I can not think of 1:30, so I also ask friends to add!

The size of the struct (and its objects) evaluated by the attribute 8:sizeof is not equal to the size of each data member Object!

The size of a struct is closely related to the alignment of struct members, not simply the sum of the size of individual Members! For example, the following structural body two structure A, b using sizeof results are: 16, 24. It can be seen that sizeof (B) is not equal to sizeof (int) +sizeof (double) +sizeof (int) = 16.

struct a{

int num1;

int num2;

Double num3;

};

struct b{

int num1;

Double num3;

int num2;

};

If you don't know the alignment of the members of the struct, you'll be amazed that the members in both the struct A and B are the same, but the order is different, why is it not the same size? To explain this, we need to understand the rules governing the alignment of struct members, as the structure member alignment is very complex, I will use the topic--c/c++ tricky question conquer bit field and member alignment-to explain, here I only briefly introduce its rules:

1. The size of the struct is equal to the integer multiple of the maximum member size of the structure body

2. The first address of a member of a struct is an integer multiple of its type size relative to the first address of the struct, for example, the address offset of a double member relative to the first address of the struct should be a multiple of 8.

3. In order to satisfy the rules 1 and 2 The compiler will make a byte fill after the struct member!

Based on the above three rules, let's see why sizeof (B) equals 24: First assume that the first address of the struct is 0, the first member NUM1 's first address is 0 (satisfies rule 2, there is no byte padding in front of it, in fact the struct will never be populated before the first data member), Its type is int, so it occupies the address space 0--3. The second member, NUM3, is a double type, which occupies 8 bytes, because the previous num1 occupies only 4 bytes, in order to satisfy rule 2, you need to use Rule 3 to populate the NUM1 with 4 bytes (4--7), which causes the num3 to have a starting address offset of 8. So the address space occupied by NUM3 is: 8--15. The third member, NUM2, is of type int, with a size of 4, because NUM1 and num3 take up 16 bytes, which can satisfy rule 2 without any padding at this time. Therefore, the address space occupied by Num2 is 16--19. So is the total size of the structure is 0--19 a total of 20 bytes? Please note that Rule 1 is not forgotten! Because the largest member of the structure body is a double that occupies 8 bytes, it is also necessary to populate the structure with 4 bytes after the num2 so that the overall size of the struct is 24.

According to the above three rules and analysis process, you can easily know why sizeof (A) equals 16. in particular , I have given three conclusive rules here, without elaborating why. You may have a lot of questions about why you want to align struct members, why you define rule 1, and so on. If you have such a question and try to figure it out, then I dare to assert that you will certainly have great success in the near future, at least in the study of C + +. As I said before, I'll write another topic:C/+ + tricky question conquer bit field and member alignment to answer these questions in detail, if you're anxious to figure out, then you can refer to other materials, such as the high quality C + + Programming Guide.

At the end of the note, it is best to carefully arrange the order of the individual members of the struct in the design, because you have seen that the structure B above is the same as the members of struct A, except that the order is slightly different, resulting in a more than 50% of the space consumed by B than a, if you need to define an array of the struct The much-consumed airborne will be huge. Even if the future memory price for cabbage prices, you do not neglect this problem, thrift is the fine tradition of the Chinese people, we should inherit and maintain!

The attribute 9:sizeof cannot be used to calculate the size of the bit-field members of a struct, but the size of the struct that contains the bit-field members can be obtained!

First explain what a bit field is: the size of the type is in bytes (byte) as the basic unit, such as sizeof (char) is 1byte,sizeof (int) is 4byte, etc. We know that the size of a type determines the range of variables that the type can define, such as sizeof (char) is 1byte, and 1byte equals 8bit, so the variable range of the char type is -128--127, or 0--255 (unsigned char), In short, it can only define the number of 28=256! However, it is fatal that the bool type only evaluates to True and False, only 1bit (i.e. 1/8byte) is sufficient, but in fact sizeof (bool) equals 1. So we can assume that the bool variable wastes 87.5% of the storage space! This is not appropriate for some devices with limited storage space (such as embedded devices), which requires a mechanism for calculating the storage space of variables, which is the bit domain. To put it simply, a colon + an integer that follows the member variable of the struct represents the bit field, see the following structure:

struct a{         Bool B:1;          Char ch1:4;          Char CH2:4;} item;

Where B,ch1,ch2 are members of a bit domain, and I is an ordinary member. The structure of the attempt to let the bool type variable B only occupy 1 bit, so that CH1 and CH2 only occupy 4 bit, so as to achieve the memory budget-conscious function ( in fact, using bit field to memory budget is sometimes successful, but not necessarily , I will Theconquer and members ' alignment of the tricky problem of C/C + + is discussed. It is also important to note that the C language specifies that bit fields can only be used for int,signed int or unsigned int, and that C + + has a char and long type added! You can't use bit fields like this: Floatf:8; this is not compiled. and bit-domain variables cannot be defined in functions or global zones , only in structs, custom classes, Union (UNION)!

Statements such as the size of a bit-field member such as the statement sizeof (ITEM.B) and sizeof (ITEM.CH1) cannot be compiled based on the structure above. The reason can be found in the introduction of this article: sizeof returns the size of the operand in bytes!

So you might want to ask, does sizeof (A) have the ability to compile? How can, and how much is the result? This is two very good questions, in fact I did not see any discussion about this (perhaps I see insufficient information), I just see that sizeof (ITEM.B) can not be compiled to think of these two issues, and then through the validation of the following conclusions: For a struct that contains bit fields, it can use sizeof to find its size, but its evaluation rules are more complex, not only related to member alignment, but also to the specific compilation environment! all you need to know here is that you can use sizeof to size a struct that contains bit fields, and for what rules sizeof is asking for this size, I'll elaborate on the topic: "Conquer and member alignment" .

Postscript:

At this point, the topic is almost over, and it needs to be explained that there is not all the knowledge about sizeof, but it almost contains all the error-prone features. To finish the article, I spent 3 and a half days, thinking that efficiency is the bottom. Because it is the first topic in this series, I am extremely cautious and I am afraid to mislead you by wrong. Even so, it is inevitable that mistakes or inappropriate, but also ask your friends to correct me!

In addition, I have a few words to the college friends said: Textbooks are usually just a very basic knowledge, want to study deeply, but also need to read other materials, such as papers, web materials, forum blog, the most important point is to learn often summed up, record, induction, added up, so adhere to a certain benefit.

The conquer of the tricky problem of C/C + + sizeof (turn)

Related Article

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.