Explanation of structures, enumerations, and unions in C language

Table of Contents

1. Structure

1.1 Structure writing format

1.2 Definition of structure variables

1.3 Structure initialization and access to members

1.4 Structure parameter passing

1.5 Structure memory size calculation

1.6 Structural body position break

1.6.1 How bit breaks allocate space

2. Enumeration

2.1 Value acquisition and assignment of enumerations

2.2 Advantages of enumeration

3. Consortium

3.1 Characteristics of union memory allocation

3.2 Calculation of the memory size of the union

Conclusion


1. Structure

In C language, putting elements of the same type into the same collection is called an array. The richness of an array is very simple because its elements are all of the same type and cannot reflect the diversity of data.

Therefore, the concept of structure is introduced. A structure can be composed of many different types of variables. These different types of variables are called member variables of the structure. With these rich values, we can depict things closer to our lives. For example, describe a person’s name + gender + hobbies + age + balance, etc.

1.1 Structure writing format

struct people//structure type
{
char name[20];//name
char sex[5];//Gender
int age;//Age
char hobby[10];//hobby
float balance;//balance
};//There must be a semicolon here

To indicate that this is a structure, you need to write struct first, followed by a custom string. The purpose is to give the structure a simple name, so the struct + custom string consists of just a structure. body type. We say that there are int type, char type, etc. These types need to be followed by a variable when used. The same is true for the structure type. When used, a variable also needs to be added at the end.

You can use typedef to rename the structure type. Generally, the structure type is considered to be too long and complicated, so typedef is used to abbreviate it.

#include<stdio.h>

typedef struct people//Structure type, this structure describes a person
{
char name[20];//name
char sex[5];//Gender
int age;//Age
char hobby[10];//hobby
float balance;//balance

}people;//At this time, the structure type changes from struct people to people

int main()
{
people a;//Use structure
return 0;
}

1.2 Definition of structure variables

#include<stdio.h>

struct people//structure type
{
char name[20];//name
char sex[5];//Gender
int age;//Age
char hobby[10];//hobby
float balance;//balance
}a1;//When creating the structure, define the structure variable a1

int main()
{
struct people a2;//Traditional way of defining variables, type + variable name a2
return 0;
}

At this time, a1 and a2 are variables defined with structure types. The definition of a structure variable can be defined directly before the semicolon after creating the structure, or it can be defined using the structure type + variable name in the main function.

1.3 Structure initialization, access to members

#include<stdio.h>

struct people//structure type
{
char name[20];//name
char sex[5];//Gender
int age;//Age
char hobby[10];//hobby
float balance;//balance
};

int main()
{
struct people a = { "Zhang San","Male",20,"Basketball",100.20 };//Create a structure variable and initialize it
printf("%s %s %d %s %.2f\\
", a.name, a.sex, a.age, a.hobby, a.balance);
return 0;
}

The variable a of the above program is created by using the structure type stryct people, and the variable a is initialized. The initialization method can be initialized one by one according to the order of the contents in the structure. For example, “Zhang San” corresponds to the char name, 20 Corresponds to the third member int age.

When printing, you need to access each member of the structure and print out the values assigned to them. At this time, you need to use the access structure operator: ‘.’ operator. The writing method is: structure variable name + ‘.’ to access the structure members.

1.4 Structure parameter passing

When passing structure parameters, you generally choose to pass the address of the structure, so the formal parameters are received using the structure pointer. Why pass the address? Because if you pass the entire structure, the formal parameters need to open up a space on the stack that is exactly the same as the structure. This is very wasteful. But if you only pass the address and the formal parameters are received by pointers, then You only need to open up a space the size of a pointer on the stack, and the pointer can also access each member of the structure.

#include<stdio.h>

typedef struct people//structure type
{
char name[20];//name
char sex[5];//Gender
int age;//Age
char hobby[10];//hobby
float balance;//balance
};

void print(struct people* pa)
{
printf("%s %s %d %s %.2f\\
", pa->name, pa->sex, pa->age, pa->hobby, pa->balance);
}

int main()
{
struct people a = { "Zhang San","Male",20,"Basketball",100.20 };
printf("%s %s %d %s %.2f\\
", a.name, a.sex, a.age, a.hobby, a.balance);
print(&a);
return 0;
}

You can also use pointers to access and print out the members of the structure. The operator you need to use is ‘->’, which is similar to an arrow operator. The writing method is: pointer + ‘->’ to access the value of the structure variable. . Of course, the pointer can also be dereferenced here and printed using the ‘.’ operator, such as: (*pa).name.

operation result:

1.5 Structure memory size calculation

This is an important point in the concept of structure knowledge. We know that the size of an int type is 4 and the size of a char type is 1. So how is the size of the structure calculated and based on what is it calculated?

Here we first introduce the concept of structure member alignment:

1. The first member of the structure is placed at position 0.

2. Starting from the second member, each member should be placed at a position that is an integer multiple of the alignment number of the member.

Alignment number = compiler default alignment number and the size of the member itself, whichever is smaller.

Under the vs compiler, the alignment number defaults to 8.

Under the gcc compiler, there is no alignment number. The alignment number is the size of the member itself.

3. The size of the structure itself must be equal to an integer multiple of the maximum alignment number of the members in the structure.

4. If there is a nested structure, then the alignment number of the nested structure is the maximum alignment number of its own members, and the size of the entire structure must also be calculated (including the alignment number of the nested structure). Counting.

An example will make it clearer:

Examples of nested relationships:

operation result:

Conclusion: Therefore, in order to reduce space and save memory, we should gather members that take up small space together.

1.6 Structural body position breaking

What is bit break? The writing method of bit breaks is similar to that of structures, but the differences are as follows:

1. The members of the bit break must be from the int family.

2. The way to write a bit break is that the member is followed by :’, the colon is followed by a number, and the number is followed by a semicolon. See the code for details.

#include<stdio.h>

struct i
{
int a : 3;
int b : 4;
int c : 20;
int d : 30;
};

int main()
{
printf("%zd\\
", sizeof(struct i));
return 0;
}

The number after the colon indicates how many bits the variable occupies. For example, variable a only occupies 3 bits, and variable c occupies 20 bits. With bit breaks, space utilization can be maximized. Extreme. There are 4 int type variables in the structure i, but the size of the structure is actually only 8 bytes.

1.6.1 How does bit interrupt allocate space

On the VS compiler, bit breaks allocate space from the low-end to the high-end of the byte. An example to prove the order of allocation:

You can observe the memory and then observe whether the binary sequence stored in the memory of structure i converted into hexadecimal form is 5c 0a 09.

It can be seen that the binary sequence stored in the memory of structure i converted to hexadecimal form is indeed 5c 0a 09. It can be proved that the order of bit allocation in the vs compiler is from right to left (from low to high) )distribute.

2. Enumeration

As the name suggests, enumeration means enumerating and arranging one by one. It gives some fixed values and possibly used values a new “title” so that they can be closely linked together. The members in the enumeration are also called enumeration constants. The enumeration is written as follows:

enum Day
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};

2.1 Enumeration value acquisition and assignment

If the enumeration constant is not assigned a value when creating the enumeration, the default is to start from 0 and go down + 1.

Although an enumeration constant is a constant, you can assign a value to it when it is first created. Then the values of the enumeration constants starting from the assigned constant will be + 1 in sequence.

2.2 Advantages of Enumeration

1. Increase the readability and maintainability of the code.

2. Enumerations are type-checked and are more rigorous than #define. For example, in a c++ environment:

It is not possible to assign an integer type value to an enumeration type variable.

3. It is more convenient to use in appropriate situations and easier to debug.

3. Consortium

A union means that the members in the body use the same memory, so it can also be called a union.

union Un
{
 char c;
 int i;
};

3.1 Characteristics of Union Memory Allocation

#include<stdio.h>

union Un
{
char c;
int i;
}u1;

int main()
{
printf("%d\\
", sizeof(u1));
return 0;
}

From a structure perspective, if you want to calculate the memory of the union, the calculated value must be 8 bytes. But judging from the results of running the program, it is not.

The reason is that char c and int i share part of the memory, which can be seen from the addresses of c and i.

The addresses of c and i are the same. In other words, if the value in c is changed, the value of a will also be affected. Then the characteristics of the union can be used to determine whether the machine is in big-endian or little-endian mode.

#include<stdio.h>

union Un
{
char c;
int i;
}u1;

int main()
{
union Un u1 = { 0 };
u1.i = 1;
if (u1.c == 1)
printf("little endian mode\\
");
else
printf("Big endian mode\\
");

return 0;
}

3.2 Calculation of the memory size of the union

After understanding the characteristics of the union, it can be deduced that its size is at least the size of the largest member occupying memory, otherwise the largest member cannot be stored. There is another point similar to the structure: if the size of the largest member is not an integer multiple of the alignment number, the size of the largest member needs to be supplemented to an integer multiple of the alignment number.

#include<stdio.h>

union Un1
{
char c[5];// Size: 5 1 8 1 Although it is an array, the alignment number is the alignment number of the char type member.
                                    //So the alignment number is 1
int i;//Size: 4 4 8 4 The alignment number is 4
//So the maximum member size is 5 bytes, and the alignment number of the structure is 4, but 5 is not an integer multiple of 4, so it is supplemented to 8 bytes
};
union Un2
{
short c[7];//Size: 14 2 8 2
int i;//Size: 4 4 8 4
//The maximum member memory is 14, the alignment number is 4, 14 plus 2 bytes = 16 bytes
};

int main()
{
printf("%zd\\
", sizeof(union Un1));//8 bytes
printf("%zd\\
", sizeof(union Un2));//16 bytes
}

Conclusion

The above is the explanation of structures, enumerations, and unions. If this article is helpful to you, I hope you can like it + follow + collect it! Oh! If there are any omissions or errors, please feel free to add them in the comment area~! ! thank you all! !