C language: the size of structures and unions (nesting)

Calculating the size of structures and unions (nesting)

In C language, structure and union are two very common data types, which are used to define a set of related data, which can make the program more flexible. In the actual application of structures and unions, it is often necessary to accurately calculate their size in order to correctly apply for memory and use these data. This blog will detail how to calculate the size of structures and unions, and how to calculate the nesting size of structures and unions.
Very detailed, I believe it will help you!

1. Data type size (64 bits)

Type Size
char 1 byte
char* (pointer variable) 8 bytes
int 4 bytes
unsigned int 4 bytes
short int 2 bytes
float 4 bytes
double 8 bytes
long 8 bytes
long long 8 bytes
unsigned long 8 bytes

2. Structure size

The default alignment follows: aligned to the least common multiple of the data type’s byte count.
The memory is arranged in the order of the members of the structure. When the member variable is arranged, the size of the space placed in front of it must be an integer multiple of the size of the member type. If it is not enough, fill it up, and so on.
In general, the size of the structure is an integer multiple of the size of the widest primitive type member of the structure. Without further ado, let’s go to the code.

demo 1

#include <stdio.h>

typedef struct
{<!-- -->
    char a[5];
    int b;
    double c;
}Test;

int main(void)
{<!-- -->
    printf("sizeof(Test) = %ld\\
",sizeof(Test));

   return 0;
}

Among them, the maximum number of type bytes is 8 bytes. char a[5] occupies 5 bytes, fills up to 8 bytes, int b occupies 4 bytes, 8 + 4=12 bytes, fills up to 16 bytes, and double c occupies 8 bytes. So: 16 + 8 = 24 bytes
Compile and run:

demo 2

The following introduces a point that needs attention in the size of the structure, which can be applied to the realization of flexible arrays, and will not be expanded here.

#include<stdio.h>

typedef struct{<!-- -->
    int num;
    char name[20];
    int arr[];
}text1;

typedef struct{<!-- -->
    int num;
    char name[20];
}text2;

int main() {<!-- -->

    printf("The size of the structure text1 is: %ld\\
", sizeof(text1));
    printf("The size of the structure text2 is: %ld\\
", sizeof(text2));
    return 0;
}

Compile and run:

It can be seen from the results that the first structure has one more parameter int arr[] than the second structure, but the final result is that the two structures have the same size. It can be explained that when calculating the structure, if there is an array with an unspecified length in the structure, then this array will be ignored during the calculation.

2. Union size

A union is also called a union. As the name implies, all data types share a piece of memory.
In short, the size of the occupied memory must be the smallest multiple of the bytes occupied by the largest type. Without further ado, let’s go to the code.

demo

#include<stdio.h>

union
{<!-- -->
    char a[7];
    int b[2];
    double c;
}Test;

int main()
{<!-- -->
    printf("sizeof(Test) = %ld\\
",sizeof(Test));

   return 0;
}

Among them, char a[7] occupies 7 bytes, int b[2] occupies 4*2=8 bytes, and 8 bytes do not need to be filled to meet the maximum type of bytes, and double c occupies 8 bytes. In summary, the maximum is 8 bytes. So, the size is 8 bytes.

If the element of member b in the above code is changed to 3, then:
The maximum byte type is double and occupies 8 bytes. char a[7] occupies 7 bytes and is filled to 8 bytes. int b[3] occupies 12 bytes and is filled to 16 bytes. In summary, the maximum is 16 bytes. So, the size of the union is 16 bytes.
Compile and run:

3. Structure and union nesting

More complex is the nested union in the structure.
Default rule: The union is calculated according to the principle that the bytes occupied by the largest member are the smallest integer multiple of the bytes corresponding to the largest data type, and the number of bytes it occupies is the sum of the bytes occupied by other members in the structure Should be the smallest multiple of bytes corresponding to the largest data type in the structure.

In short, the innermost union is calculated first, and then the normal method calculates the bytes occupied by other members of the structure. The last thing to align is the largest byte type in the structure. Without further ado, let’s go to the code.

demo 1

#include<stdio.h>

typedef struct
{<!-- -->
    union
    {<!-- -->
        char a[10];
        int b[2];
        double c;
    } test;

    char d[5];
    int e;
    double f;
}Test;

int main()
{<!-- -->
    printf("sizeof(Test) = %ld\\
",sizeof(Test));

    return 0;
}

In the first calculation of the union, the largest char a[10] occupies 10 bytes, but it must be the smallest multiple of 8, so the union occupies 16 bytes.
Then the remaining 5 + 4 + 8=17 bytes in the structure are not the minimum multiple of 8 bytes corresponding to the largest data type double in the structure, and are filled to 24 bytes.
Therefore, the combined size of the entire structure: 16 (bytes occupied by the union) + 24 bytes = 40 bytes
Compile and run:

demo 2

Since the calculation of the size of the structure and the union is a high-frequency test site for written tests and interviews when looking for a job, here is a c language written test question from a certain company.

#include<stdio.h>

typedef union
{<!-- -->
    long i;
    int k[5];
    char c;
}DATE;

typedef struct
{<!-- -->
    int cat;
    DATE cow;
    double dog;
}data;

DATE max;

int main()
{<!-- -->
    printf("result:%ld\\
",sizeof(data) + sizeof(max));

}


Calculate the size of the union first: the maximum int k[5] occupies 20 bytes, and it is filled to 24 bytes. So a DATE is 24 bytes.
Then calculate the size of the remaining members of the structure: 4 + 4 + 8=16 bytes
Then calculate the real size of the structure: 24 + 16 = 40 bytes
Finally sizeof(data) + sizeof(max): 40 + 24 = 64 bytes

4. Specify byte alignment

When we need to specify byte alignment, we need to define #pragma pack(value), which specifies value byte alignment. It will be easier to understand directly with the code demonstration.

demo 1

Structural alignment rules: the overall size must be the smallest integer multiple of value.

#include<stdio.h>

#pragma pack(4)

typedef struct
{<!-- -->
    char a[5];
    int b;
    double c;
}Test;

int main()
{<!-- -->
    printf("sizeof(Test) = %ld\\
",sizeof(Test));

    return 0;
}

Among them, the calculation is based on 4-byte alignment here, and the member char a[5] occupies 5 bytes, which is filled to 8 bytes.
int b occupies 4 bytes, and double c occupies 8 bytes, both of which are multiples of 4 and do not need to be filled. So: the overall size is 8 + 4 + 8 = 20 bytes.
Compile and run:

demo 2

Union alignment rule: The bytes occupied by the largest member in the union must be the minimum multiple of value.

#include<stdio.h>

#pragma pack(2)
union
{<!-- -->
    char a[7];
    int b[3];
    double c;
}Test;

int main(void)
{<!-- -->
    printf("sizeof(Test) = %ld\\
",sizeof(Test));

    return 0;
}

Specifies the alignment of 2 bytes, char a[7] occupies 7 bytes, and is filled with 8 bytes, which is a minimum multiple of 2. int b[3] occupies 12 bytes and does not need to be filled. Double c is 8 bytes, no padding is required. So, the maximum is 12 bytes.
Compile and run:

5. Summary

Seeing this, I believe everyone is very clear about calculating the size of structures and unions (nesting), just pay attention to aligning with the data type of the largest byte. If there are any deficiencies, everyone is welcome to discuss in the comment area.
If you find it useful, please like and collect it.