C + + tricky problem to detail sizeof__c++

Source: Internet
Author: User

Summary:

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

(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 void type pointer;

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

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

(5) The sizeof cannot be length to the incomplete array;

(6) When an expression is a sizeof operand, it returns the type size of the evaluated result of an expression, but it does not evaluate the expression.

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

(8) The size of the structure body (and its object) sizeof is not equal to the size of each data member object.

(9) sizeof cannot be used to find the size of a bit-domain member of a struct, but the size of a struct that contains a bit-domain member can be evaluated.

Overview:

sizeof is a keyword in c/s + +, which is an operator that takes the length of an object ( data type or data Object ) (that is, the size of the memory, in bytes ). The types contain basic data types (excluding void), user-defined types (structs, classes), function types . A data object is a generic variable and a pointer variable (containing a void pointer) defined with the previously mentioned type. The size of the different types of data varies between platforms, but the C standard stipulates that all compilation platforms should ensure that sizeof (char) equals 1. For more information on sizeof you can query the MSDN total input sizeof.

Look at these, maybe you did not see much feeling. Okay, here's a list of sizeof features that make sizeof a more tricky keyword:

Ten Features:

attribute 0:sizeof is an operator, not a function

This characteristic is the most basic characteristic of sizeof, many of the later features 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 call the operand (this is not rigorous, but help me remember that sizeof is an operator).

attribute 1:sizeof cannot obtain length of void type

Yes, you cannot use sizeof (void), which will result in compilation errors: illegalsizeof operand. In fact, you simply cannot declare a variable of type void, and you try void A; The compiler also complains: illegal use of type ' void '. Perhaps you want to ask why, very good, learn things can not only know it, but also know why. We know that one important function of declaring variables is to tell the compiler how much storage space is required for that variable. However, void is a "null 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 to a void type. This is the content of feature 2.

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

As stated in feature 1, a pointer to a void type can be declared, meaning that the compiler can determine the amount of storage space occupied by a pointer of type void. As a matter of fact, at present, all versions of the compiler on almost all platforms regard the size of the pointer as 4byte, and do not believe you try sizeof (int*); sizeof (void*); sizeof (double*); sizeof (person*); They all equal 4. Why, then? 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 other variables . And because the current 32-bit computer platform to address the scope of the program segment is 4GB, addressing the smallest unit is BYTE,4GB equal to 232Byte, so much memory its address if encoded, only need to use 32 bit on the line, and 32bit = 32/8 = 4byte, That is, it takes only 4byte to store these memory addresses. Therefore, the result of sizeof operations on any type of pointer variable is 4.

attribute 3:sizeof can obtain the length of the array of statically allocated memory!

Int a[10];int n = sizeof (a); assuming that sizeof (int) equals 4, then n= 10*4=40; Pay special attention to: charch[]= "abc"; sizeof (ch); The result is 4, note that the end of the string array has ' '. In general, we can use sizeof to compute the number of elements contained in an array by: int n = sizeof (a)/sizeof (a[0));

It is important to note the case of using sizeof for the parameter groups of the function. For example, suppose the following function:

void fun (int array[10])

{

int n = sizeof (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 parameter is an array of int, a float array, or an array of any other user-defined type, and no matter how many elements the array contains, the N is 4. Why, then? The reason is that when the function parameter is passed, the array is converted to a pointer, perhaps you have to ask why to translate the pointer, the reason can be found in a lot of books, I simply said: If the whole array of direct transmission, then necessarily involve the copy of the elements of the array (arguments to the copy of the parameters), when the array is very large, This results in extremely inefficient function execution. Instead, only the address of the array (that is, the pointer) is only required to copy 4byte.

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

If you have the following statement: int*a = new Int[10];int n = sizeof (a); then what is the value of n? Is it 40? The answer is in the negative. In fact, N equals 4 because A is a pointer, and it is said in feature 2 that all pointers are 4byte in size on 32-bit platforms. Remember that a is not the same as the A in feature 3. Many people (even some teachers) think that the array name is a pointer, actually, there are many differences between the two, for details, please see "c Expert programming." With feature 3 and feature 4, we see that arrays and pointers are inextricably linked, and that these relationships are a major factor in the potential error of the program, and the relationship between pointers and arrays I will explain in detail in the article "TheSecrets of the pointers and arrays of C + + tricky problems ".

Feature 3 indicates that sizeof can find the size of statically allocated arrays, while feature 4 describes the size of the dynamically allocated memory that sizeof cannot find. So some people think that sizeof is evaluated at compile time, and gives the reason: statement int array[sizeof (int) *10]; can be compiled, and many books have said that the size of the array is at compile time to determine, since the preceding statement can be compiled through, So the sizeof is considered to be 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: the statement: int num;cin>>num; int Arrary[num]; it's right (note that it's wrong in the vc6.0). So I used the statement int n=sizeof (array) for the array in dev C + +, Cout<<n<<endl to size, the result was compiled, and after the runtime entered Num's value of 10, Output n equals 40. It is obvious here that the value of NUM is entered only at runtime, so it is not possible for sizeof to get the size of the array at compile time. This sizeof again becomes the run-time evaluation.

So in the end sizeof is compile-time evaluation or run-time evaluation of the value. The most initial C standard stipulates that sizeof can only be evaluated at compile time, and later C99 add the stipulation that sizeof can be evaluated at run time. However, it is worth noting that even in Dev C + +, which implements the C99 standard, the size of dynamically allocated memory is still not available in sizeof.

attribute 5:sizeof cannot evaluate an incomplete array for length.

Before we explain this feature, we assume that there are two source files: File1.cpp and File2.cpp, where file1.cpp is defined as follows:

int arraya[10] = {1,2,3,4,5,6,7,8,9,10};

int arrayb[10] = {11,12,13,14,15,16,17,18,19,20};

File2.cpp contains the following statements:

Externarraya[];

EXTERNARRAYB[10];

Cout<<sizeof (Arraya) <<endl; Compilation error.

Cout<<sizeof (Arrayb) <<endl;

The third statement in File2.cpp has an error compiling, and the first statement is correct and can output 40. Why, then? The reason is that sizeof (Arraya) is trying to find the size of an incomplete array. The incomplete array here is an array with no definite index group size. The function of the sizeof operator is to find the size of an object, but declare that an extern int arraya[] simply tells the compiler that Arraya is an integer array, but does not tell the compiler how many elements it contains. So for the sizeof in File2.cpp it can't find the size of the Arraya, so the compiler simply won't let you compile.

So why does sizeof (ARRAYB) Get the size of Arraryb? The key is to use Externint arrayb[10 when declaring in File2.cpp explicitly telling the compiler that ARRAYB is an integral array of 10 elements, The size is therefore determined.

The explanation for this feature is almost over. In fact, this issue can be extended to Connect and compile knowledge points, but at present I do not have the confidence of these two knowledge points for detailed, thorough explanation, so inconvenience in this teaching, in the near future I will add related issues in this series of elaboration.

attribute 6: When an expression is the operand of a sizeof, it returns the type size of the evaluated result of the expression, but it does not evaluate the expression.

To illustrate this issue, let's look at the following program statement:

char ch = 1;

int num=1;

int N1 =sizeof (ch+num);

int n2 = sizeof (ch =ch+num);

Assuming that Char occupies 1byte,int 4byte, what is the value of n1,n2,ch after executing the above program? I believe that many 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, why? Please see analysis:

The expression ch+num evaluates to an int because of the reason for the default type conversion, so the N1 value is 4. The type of the result of the expression Ch=ch+num is char, and remember that although the result is int when the ch+num is computed, the final type of the expression is char when the result is assigned to CH, so the N2 equals 1. The N1,N2 values are 4 and 1, because the sizeof returns the type size of the expression evaluation result, not the size of the variable that occupies the maximum 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 and assigning it to CH, and that's not the case. Because sizeof only care about the size of the type, so it should not be evaluated on the expression, otherwise there is a suspicion of the superfluous. It is precisely because of this, here warns you, as far as possible not in the sizeof directly to the expression size, in order to avoid errors, you can sizeof (ch = ch+num), change to write ch = ch +num;sizeof (CH), although one more statement, seemingly redundant, In fact, there are many benefits: first clearer, followed by no ch equals 1 errors (assuming that the logic of the program itself is to execute ch = ch +num;).

attribute 7:sizeof can be sized on a function call, and the size of the value is equal to the size of the return type, but the function body is not executed.

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

int fun (int& num,const int& Inc.)

{

float div = 2.0;

DOUBLE ret = 0;

num = num+inc;

ret = Num/div;

return ret;

Then the statement:

int a = 3;

int b = 5;

Cout<<sizeof (Fun (a,b)) <<endl;

How much does the cout<<a<<endl; output? Different people will give different answers, and I will discuss the value of sizeof (Fun (a,b)) and the value of a, respectively:

First sizeof (Fun (A,B)): Its correct is 4, because when the function call is evaluated by sizeof, it gets the size of the function return type , 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 , and think that the value of sizeof (A,B) is 8 because the function return value is a RET, and a 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 type-converted (the conversion here is unsafe). It is also mistaken to think that the value of sizeof (Fun (A,B)) is 12, and their reason is that fun internally defines two local variables, one is float and one is double, and sizeof (float) +sizeof (doube) = 4+8=12. Such an answer seems reasonable, in fact they are mistakenly think that the sizeof here is the size of the variables inside the function. This is, of course, wrong.

Next look at the value of a: The correct answer is 3. Remember the feature 6? This is similar to the case where the sizeof action object is a function call, and it does not execute the function body. To this end, we recommend that you do not put the function body in parentheses behind the sizeof, so that people mistakenly think that the function is executed, in fact it did not execute.

Since the function bar uses sizeof to get the size of the function return type, it is natural to conclude that a function with a return type of void cannot be used to sizeof its size. For reasons please refer to feature 1. Similarly, a function call to a return type that is any type of pointer uses sizeof to obtain a size of 4, for reasons refer to feature 2.

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

The size of the structure body (and its object) evaluated by the attribute 8:sizeof is not equal to the size of each data member object.

The size of the structure is closely related to the alignment of the members of the structure, and is not simply equal to the size of each member. For example, the results of using sizeof in two structures A and b of the following structural bodies are: 16, 24. You can see 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 do not understand the alignment of the members of the structure, you will be surprised that the members of the structure A and B are the same, but in a different order, why they are not the same size. To explain this problem, it is important to understand the rules of the structure member alignment, because the structure member alignment is very complex, I will use the topic--c/c++ tricky problem-by-bit domain and member alignment--to explain, here I simply introduce its rules:

1, the size of the structure is equal to the maximum member size of the structure of the integer multiple times

2, the initial address of the member of the structure body relative to the first address of the structure body is an integer multiple of its type size, such as the address offset of the double member relative to the first address of the structure body should be a multiple of 8.

3, in order to meet the rules 1 and 2 The compiler will be in the structure of the member after the byte fill.

Based on the above three rules, let's see why sizeof (B) equals 24: First, assuming that the first address of the struct body is 0, the first address of NUM1 is 0 (satisfies Rule 2, preceded by no byte padding, and in fact the structure is never preceded by byte padding in front of the first data member), Its type is int, so it occupies the address space 0--3. The second member, NUM3, is a double that takes up 8 bytes, and because the previous Num1 occupies only 4 bytes, to meet rule 2, you need to populate 4 bytes (4--7) with Rule 3 after the NUM1, making the num3 start address offset to 8, Therefore, the address space occupied by NUM3 is: 8--15. The third member, NUM2, is an int with a size of 4, and since Num1 and num3 occupy 16 bytes, the rule 2 can be met without any padding at this time. Therefore, the address space occupied by Num2 is 16--19. So is not 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 finally necessary to populate the Num2 with 4 bytes, making the overall size of the structure 24.

According to the above three rules and analysis process, you can easily know why sizeof (A) equals 16. It is particularly necessary to note that I have given three conclusive rules here, without elaborating why. You may have a lot of questions about why you want to align the members of the structure, and why you should define rule 1. If you have such a question and try to figure it out, then I'm sure you will have great success in the near future, at least in learning C + +. As I said before, I will write a special topic:C + + tricky problem the bit field and the member alignment to answer these questions in detail, if you are anxious to understand, then you can refer to other information, such as "High-quality C + + Programming Guide."

Finally, in the design, it is best to carefully arrange the order of the members in the structure, 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 50% more space consumed by B than a, if an array of the structure is to be defined in the project, The much-consumed airborne will be immense. Even if the future of memory prices to the price of cabbage, you do not ignore this problem, thrift is the Chinese people's fine tradition, we should inherit and maintain.

attribute 9:sizeof cannot be used to evaluate the size of a bit-domain member of a struct, but the size of a struct that contains a bit-domain member can be evaluated.

First, explain what a bit field is: the size of the type is in bytes (byte), for example, sizeof (char) is 1byte,sizeof (int) is 4byte. We know that the size of a type determines the range of variables that the type can define, such as sizeof (char) 1byte, and 1byte equals 8bit, so the variable range of char type is -128--127, or 0--255 (unsigned char), In short, it can only define 28 = 256 numbers. However, it is fatal that the bool type only evaluates to True and false, and that the only 1bit (i.e. 1/8byte) is enough, but in fact sizeof (bool) equals 1. So we can think 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, to provide a mechanism for calculating the storage space of variables, which is the bit domain. Simply put, a colon + an integer that follows the member variable of the struct body , representing the bit field, looks at the following structural body:

Struct A

{

Bool b:1;

Char Ch1:4;

Char Ch2:4;

}item; Where B,CH1,CH2 is a bit-domain member, and I is an ordinary member. The structure is trying to make variable B of type bool occupy only 1 bits, so that CH1 and CH2 occupy only 4 bits, which can be used to calculate the memory function ( in fact, use the bit field to the memory of the time to be successful, sometimes it is not , I will "C + + tricky problem-and-point domain and member alignment" is discussed. In addition, it is necessary to note that the C language requires that the bit fields be used only for int,signed int or unsigned int types, and C + + adds char and long types. you can't do this. Use bit fields: floatf:8; this is not compiled. also, a bit field variable cannot be defined in a function or global area and can only be used in a struct, custom class, Union (Union).

Based on the structure above, statements such as statements sizeof (ITEM.B) and sizeof (ITEM.CH1) for size to bit domain members cannot be compiled. The reason can be found in the introduction of this article: sizeof returns the size of the operand in bytes.

So love to learn to ask you may ask, sizeof (A) can be compiled. How can it be, and how much is the result? This is two very good questions, in fact I have not seen any discussion of this in the past (perhaps I do not see enough information), I was seeing sizeof (ITEM.B) can not compile the two problems, and then through the verification of the following conclusions: It is possible to use sizeof to size a struct that contains a bit field, but its evaluation rules are more complex, involving not only member alignment but also the specific compilation environment. all you need to know is that you can use sizeof to size the structure that contains the bit fields, for the sizeof is based on what rules to find the size of the problem, I will be in the special topic: "C + + tricky problem-solving the bit domain and member alignment" in detail .

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.