A brief introduction to sizeof of

  • 2020-04-01 21:41:02
  • OfStack

(I) basic concepts

      The sizeof operator gives the storage sizeof its operands in bytes. An operand can be an expression or a type name enclosed in parentheses. The storage size of the operands is determined by the type of operands.

(2) method of use

1. For data types

      Sizeof use form: sizeof (type), as sizeof (int)

2. For variables

      Sizeof USES sizeof (var_name) or sizeof var_name

      Variable names can be enclosed without parentheses. Sizeof (var_name), sizeof var_name, and so on are in the correct form. The use of parentheses is more common, and most programmers take this form.

      Note: the sizeof operator cannot be used for function types, incomplete types, or bit fields. Incomplete type refers to data type with unknown storage size, such as array type with unknown storage size, structure of unknown content or union type, void type, etc.

      For example,sizeof(Max) if the variable Max is defined as int Max (),sizeof(char_v) if char_v is defined as char char_v [Max] and Max is unknown,sizeof(void) is not the correct form.

(3) the case of sizeof applied on the structure

      Look at the structure below:


struct MyStruct 
{    
double doub; 
char ch;   
int i;
};

    What happens if I take sizeof of the structure MyStruct? What is sizeof of MyStruct? You might ask:

    Sizeof (MyStruct) = sizeof (double) + sizeof (char) + sizeof (int) = 13

Here is the test code:


#include 
using namespace std;
struct MyStruct
{
    double doub;
    char ch;
    int i;
};
int main()
{
    MyStruct ms;
    cout << sizeof(ms) << endl;
    return 0;
}

Test results:

< img border = 0 SRC = "/ / files.jb51.net/file_images/article/201304/2013425115235253.jpg" >

    But when you test the sizeof the above structure in VC, you will find that sizeof(ms) is 16. In fact, this is a special treatment of variable storage by VC. In order to improve the CPU storage speed, VC "allocates" the starting addresses of some variables. By default, VC specifies that the offset between the starting address of each member variable and the starting address of the structure must be a multiple of the number of bytes occupied by the variable's type.

Alignment of commonly used types

type Alignment (the offset of the starting address of the variable to the starting address of the structure) char The offset must be sizeof(char), which is a multiple of 1 int The offset must be sizeof(int), which is a multiple of 4 A double The offset must be sizeof(double), which is a multiple of 8 short The offset must be sizeof(short), which is a multiple of 2 float The offset must be sizeof(float), which is a multiple of 4

When the member variables are stored, they apply for space in turn according to the order they appear in the structure. At the same time, they adjust the position according to the above alignment, and the empty byte VC will be filled automatically. At the same time, VC ensures that the size of the structure is a multiple of the byte boundary number of the structure (that is, the number of bytes occupied by the type occupying the largest space in the structure), so after the space is applied for the last member variable, the empty bytes are automatically filled as needed.


struct MyStruct
{
    double doub;
    char ch;
    int i;
};

    When allocating space for the above structure, VC first allocates space for the first member doub according to the order and alignment of the member variables. The starting address is the same as the starting address of the structure (the offset 0 is just a multiple of sizeof(double)). The member variable occupies sizeof(double)=8 bytes. Next, allocate the space for the second member ch. At this time, the offset of the next address that can be allocated to the starting address of the structure is 8, which is a multiple of sizeof(char). Therefore, the place where the ch is stored at the offset of 8 satisfies the alignment. Next I allocate space for the third members, then the address of the next can be allocated to the starting address of the structure of the offset of 9, not sizeof (int) = 4 times, in order to meet the alignment to offset the constraints of the problem, VC automatically fill 3 bytes (the three bytes there anything), then the address of the next can be allocated to structure the starting address of the offset is 12, just sizeof (int) = 4 multiples, so keep the I in offset to 12, the member variables occupy sizeof (int) = 4 bytes; At this point, the member variables of the entire structure have been allocated space, and the total space occupied is: 8+1+3+4=16, which is just a multiple of the byte boundary number of the structure (that is, the sizeof sizeof(double)=8) occupied by the type occupying the largest space in the structure, so there are no empty bytes to fill. So the sizeof the whole structure is: sizeof(MyStruct)=8+1+3+4=16, in which 3 bytes are automatically filled by VC and nothing meaningful is put.

      For another example, swap the position of the member variable of the above MyStruct to make it the following:


struct MyStruct
{
    char ch;
    double doub;
    int i;
};

      In the VC environment, you can get sizeof(MyStruct) is 24. Combined with some principles of space allocation mentioned above, analyze how VC allocates space for the above structure:


struct MyStruct
{
    char ch;        //The offset is 0, which satisfies the alignment mode. The ch occupies 1 byte.
    double doub;    //The next available address has an offset of 1, not sizeof(double)=8
                    //To make the offset to 8 (which satisfies alignment)
                    //So VC is automatically filled with 7 bytes, and doub is stored at an offset of 8
                    //It takes 8 bytes on the address of.
    int i;            //The next available address has an offset of 16, which is times sizeof(int)=4
                    //Number, satisfy the alignment of int, so you don't need VC to fill automatically, I save
                    //On an address with an offset of 16, it takes four bytes.
};                    //All member variables are allocated space, the total size of the space is 1+7+8+4=20, not the structure
                    //Is the number of bytes sizeof occupied by the type that takes up the most space in the structure
                    //(double)=8), so you need to fill in 4 bytes to satisfy the size of the structure
                    //Sizeof (double)= a multiple of 8.

      So the total sizeof the structure is: sizeof(MyStruct) is 1+7+8+4+4=24. There is a total of 7+4=11 bytes that VC automatically fills, and nothing meaningful is put in it.

      VC's special treatment of structured storage does increase the speed of CPU's storage of variables, but sometimes it also brings some trouble. We also mask the default alignment of variables, and we can set the alignment of variables.

      VC provides #pragma pack(n) to align variables in n bytes. N byte alignment is the starting address of the variable for the offset of two things: first, if n is greater than or equal to the variable of the number of bytes occupied, then the offset must meet the alignment of the default, second, if n is less than the type of the variable of the number of bytes occupied, then the offset for n times, don't have to meet the default alignment. The total size of the structure also has a constraint, which is divided into two cases: if n is greater than the number of bytes occupied by all the member variable types, then the total size of the structure must be a multiple of the number of space occupied by the variable with the largest space; Otherwise it has to be a multiple of n.

The following examples illustrate their usage:


#pragma pack(push)  //Save alignment
#pragma pack(4)        //Set to 4-byte alignment
struct MyStruct 
{ 
    char ch; 
    double doub; 
    int i; 
}; 
#pragma pack(pop)    //Restore alignment

Test results:

< img border = 0 SRC = "/ / files.jb51.net/file_images/article/201304/2013425115742314.jpg" >

(4) summary of sizeof usage

1. Parameters are data types or general variables.

      For example,sizeof(int),sizeof(long), and so on. The important thing to note in this case is that the results may vary from system to system or compiler to compiler. For example, an int type takes 2 bytes in a 16-bit system and 4 bytes in a 32-bit system.

2. The parameters are arrays or Pointers.

      Here's an example.


int a[50];         //Sizeof (a) = 4 * 50 = 200; Find how much space an array takes up
int *a = new int[50]; //Sizeof (a) = 4; A is a pointer, sizeof(a) is the sizeof the pointer, in a 32-bit system, of course, is four bytes.

3.   The parameter is other.


int func(char s[5])
{ 
    return 1;              //The argument to the function is handled by the system as a pointer when passed, so sizeof(s) is actually the sizeof the pointer.
} 
sizeof(func("1234")); //Since the return type of func is int, it is equivalent to sizeof(int) with a value of 4.


Related articles: