[Custom Type] Take you into the structure, enumeration, union

Welcome to Xiao Wang's blog of learning code

After the character function, the next thing we need to learn is the structure, enumeration and union in the custom type

Table of contents

foreword

1. Structure

1.1 Declaration of structure

1.2 Special declarations and structural self-references

1.4 Self-reference of structure

1.5 Definition and initialization of structure variables

1.6 Structure memory alignment

1.7 Modify the default alignment number

1.8 Structure parameter passing

Two, enumeration

1. Definition of enumeration

2. Advantages of enumeration

3. Use of enumeration

 3. Union (community)

1. Definition of union

2. The characteristics of the joint

3. Calculation of joint size

4. Practice questions

Summarize


foreword

We know that there are built-in data types and custom types in C language. For details, please refer to [C Language Advanced] In-depth analysis of data storage in memory_Xiaowang Xuecode Blog-CSDN Blog

Next, let's introduce in detail what are structures, enumerations, and unions in custom types, and how to use them?

1. Structure

A structure is a collection of values ​​called member variables , and each member of the structure can be a variable of a different type

1.1 Declaration of structure

 Practical code demo:

struct Stu {//学生结构体
	char name[20];//姓名
	int age;//年龄
	char id[20];//学号
};//分号是自带的,不能丢失,
int main()
{
	struct Stu stu = { "name",12,"123456" };
	return 0;
}

1.2 Special declarations and structural self-references

When declaring a structure, you can use incomplete declaration, which is possible at this time, but you must set the global variable before the semicolon, otherwise you cannot find this structure (anonymous structure)

Demo:

struct {
	int age;
	char name[20];
}x;
//是可以这样没有标签的,但是前提是创建x这样的全局变量,否则之后就找不到了
//因为是匿名结构体
struct {
	int age;
	char name[20];
}a[10],*p;
int main()
{
	
	scanf("%s", x.name);
	printf("%s", x.name);
	p = &x;
//非法的,因为p和x不是指向同一个结构体类型的,虽然成员变量一样,但是实际上类型是不同的
	return 0;
}

Next, let's think about whether the first and second structures of the above code are the same , can  p=&x  ?

Graphic:

As explained above, the compiler will treat the declarations of the above two structures as two completely different types, so it is illegal

1.4 Self-reference of structure

The self-reference of the structure is mostly used on the side of the data structure, such as sequence list, linked list, etc. Next, let’s introduce it, the declaration is called the self-reference of the structure

The self-reference of the structure, as the name implies, uses the member variables of the structure type inside the structure

Graphic:

Code demo:

//正确的自引用方式   有*号
struct Node
{
int data;
struct Node* next;
};
//错误的方式   没有*号
struct Node
{
int data;
struct Node next;
};

1.5 Definition and initialization of structure variables

Above we introduced how to declare, then let's take a look at how to use the structure, initialize and define it

Code demo:

struct Point {
	int x;
	int y;
}p1;			//声明类型的同时进行定义变量p1  这个是全局变量

struct Point p2;	//这也是定义结构体变量,在结构体外面,函数外面,这也是全局变量

//初始化,定义变量的同时进行赋初值
struct Point p3 = { 1,2 };

struct Stu {
	char name[20];//姓名
	int age;//年龄
};

struct Stu s = { "why",20 };//初始化,这也是全局变量

struct Node {
	int date;
	struct Point p;
	struct Node* next;
}n1={10,{1,2},NULL};	//结构体嵌套初始化

struct Node n2 = { 10,{1,2},NULL };//结构体嵌套初始化

How to assign and initialize the rest:

struct Point
{
	int x;
	int y;
}p1 = {10, 20};

struct Point p2 = {0,0};

struct S
{
	int num;
	char ch;
	struct Point p;
	float d;
};

int main()
{
	struct Point p3 = {1,2};
	struct S s = { 100, 'w', {2,5}, 3.14f};
//这些属于基础的部分,赋值需要使用大括号,内部如果有其他类型的结构体,也要进行使用大括号
	struct S s2 = {.d=1.2f, .p.x=3,.p.y=5, .ch = 'q', .num=200};
	//创建一个变量之后,可以使用 .d=1.2f 这样的形式进行赋值,可以不用考虑结构体成员变量的顺序

	printf("%d %c %d %d %f\n", s.num, s.ch, s.p.x, s.p.y, s.d);
	printf("%d %c %d %d %f\n", s2.num, s2.ch, s2.p.x, s2.p.y, s2.d);

	return 0;
}

1.6 Structure memory alignment

above. We have basically understood the basic use of structures.

We all know that data types will occupy space in memory, let's take a deeper look at calculating the size of the structure

This is a very important knowledge point: structure memory alignment

What is memory alignment? How is it aligned? There are the following rules

1. The first member is at the address whose offset from the structure variable is 0.
2. Other member variables should be aligned to an address that is an integer multiple of a certain number (alignment number).
    Alignment = Compiler's default alignment and the smaller value of the member size .
   The default value in VS is 8 3. The total size
of the structure is an integer multiple of the maximum alignment (each member variable has an alignment) . 4. If a structure is nested , the nested structure is aligned to an integer multiple of its own maximum alignment, and the overall size of the structure is the integer of all maximum alignments (including the alignment of the nested structure) times.

Code demo:


struct s1 {
	char c1;
	int i;
	char c2;
};
struct s2 {
	char c1;
	char c2;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct s1));
	printf("%d\n", sizeof(struct s2));
	return 0;
}

Graphic analysis explanation:

 Why does memory alignment exist?

explain:

1. Platform reason (transplant reason):
Not all hardware platforms can access any data at any address; some hardware platforms can only fetch certain types of data at certain addresses, otherwise a hardware exception will be thrown.
2. Performance reasons:
data structures (especially stacks) should be aligned on natural boundaries as much as possible.
The reason is that to access unaligned memory, the processor needs to make two memory accesses; while aligned memory accesses require only one access.
In short: the memory alignment of the structure is the practice of exchanging space for time! ! !

Therefore, in the design of the structure in the future, we should try our best to meet the alignment and save space, so we should

Let the members who occupy a small space gather together as much as possible! ! !

1.7 Modify the default alignment number

We can use the #pragma preprocessing directive to change the default alignment (the default alignment varies in different compilers)

#pragma pack(num) modify the default offset to num

#pragma pack () means to cancel the default offset set before and return to the compiler default offset

Code demo:

#pragma pack(4)//设置默认对齐数为4

struct s3 {
	char c1;
	int i;
	char c2;
	double c;
};
#pragma pack()//再次使用这个预处理宏,会取消设置的默认对齐数

#pragma pack(1)//设置最大对齐数为1
struct s4 {
	char c1;
	int i;
	char c2;
	double c;
};

int main()
{
	printf("%d ", sizeof(struct s3));
	printf("%d", sizeof(struct s4));

	return 0;
}

So after learning to use #pragma pack(), you can change the default alignment number yourself when the structure alignment is not appropriate

1.8 Structure parameter passing

We have two ways to pass parameters, the first pass structure, the second pass address, which one is better?

Code demo:

//传参:1.传递结构体,2.传递地址
struct s3 {
	int data;
};
struct s3 s = { 1000 };

void print1(struct s3 s)//传递结构体
{
	printf("%d  ", s.data);
}
void print2(struct s3* s) {//传递地址
	printf("%d", s->data);
}
int main() {
	print1(s);//传递结构体
	print2(&s);//传递地址
}

In the two methods, because the address is passed, the space will not be applied again when the formal parameter is created, and the memory of the structure is generally relatively large, so in order to better save costs, we prefer to pass the address

1. When a function passes parameters, the parameters need to be pushed onto the stack, which will cause system overhead in time and space.
2. If a structure object is passed, the structure is too large, and the system overhead of pushing the parameters to the stack is relatively large, which will lead to a decrease in performance

Two, enumeration

1. Definition of enumeration

Enumeration is to enumerate all kinds of possibilities one by one.

List all possible values ​​one by one, such as seven days a week, so you can list Monday, Tuesday....

Code demo:

enum Day//星期
{
Mon,
Tues,   //枚举成员之间使用逗号隔开
Wed,
Thur,
Fri,
Sat,
Sun   //且枚举的成员的取值是从0开始的,逐渐+1
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED,
GREEN,
BLUE
};
int main()
{
	printf("%d\n", Mon);
	printf("%d\n", Tues);
	printf("%d\n", Wed);
	printf("%d\n", Thur);
	printf("%d\n", Fri);
	printf("%d\n", Sat);
	printf("%d\n", Sun);
	return 0;
}

Graphic presentation: 

 The enum Day , enum Sex , and enum Color defined above are all enumeration types.
 The content in {} is the possible value of the enumeration type, also called enumeration constant.
 These possible values ​​are all valuable, starting from 0 by default, incrementing by 1 at a time, of course, the initial value can also be assigned when defining

enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};

2. Advantages of enumeration

Why use enumeration, there is something like enumeration enum and structure?

Some friends can see that enumeration is not a collection of constants defined by #define, so what does it mean to create an enumeration?

What are the benefits?

Advantages of enums:

1. Increase the readability and maintainability of the code
2. Compared with the identifier defined by #define, the enumeration has type checking, which is more rigorous.
3. Prevent naming pollution (encapsulation)
4. Easy to debug
5. Easy to use, multiple constants can be defined at a time

3. Use of enumeration

We have now understood the definition of enumeration, what is enumeration, and what are the advantages of enumeration? Finally, let's get to know how to use enumeration and how to use it correctly?

Graphic presentation:

 3. Union (community)

1. Definition of union

Unions are a special custom type

Variables defined by this type are also similar to structures and have a series of members. The characteristic is that these members share the same space

for example:

In fact, union is to use a space together. When one member variable is changed, another member variable may also be changed. This is more suitable, one is used, and the other is not applicable.

2. The characteristics of the joint

The members of the union share the same memory space , and the size of such a joint variable is at least the size of the largest member ( because the union must at least be able to save the largest member ).

So let's take a look, what is the initial address of the members in the union? Is it the same?

Code demo:

3. Calculation of joint size

We learned above that there are many rules for calculating the memory size of a structure. If you feel that the calculation is a bit troublesome, then the union is very simple. only two dots

1. The size of the union is at least the size of the largest member.     
2. When the maximum member size is not an integer multiple of the maximum alignment number, it must be aligned to an integer multiple of the maximum alignment number

First case: 

(That is to say, whoever is the largest can be used. When there is no array or structure, there are only basic built-in types )

This size is the byte size of the largest type

Second case:

Code demo:

union un1 {
	char c[5];//5个char类型为5字节
	int i;//;两种类型int char 所以最后结果为4 的倍数
	//5>4  所以最后为8
};
union un2 {
	short c[7];//相当于7个short类型连着  这样是14个字节
	int i;//un2 中 类型一共两种  int short  所以int为最大类型,所以最后得到的数据应该是4的倍数
	//因为是联合 所以14是这两个联合起来其中最大的一个, 再取4的倍数 ,得到16
};

int main()
{
	printf("%d\n", sizeof(union un1));//8
	printf("%d\n", sizeof(union un2));//16

	return 0;
}

4. Practice questions

How to verify that the current compiler is endian

When we learned pointers before, we learned the first method. Please refer to the big and small end [C language advanced] in-depth analysis of data storage in memory_Xiaowang Xuecode Blog-CSDN Blog

Next, let's see how to test with union?

code show as below:

 Therefore, it is little endian in the VS environment.


Summarize

In this chapter, we learned the definition of structure, how to declare, self-reference, definition and initialization of structure variables, structure memory alignment, and how to modify the default alignment. Then, for the understanding of enumeration, and the use, and finally the definition characteristics of the joint and how to calculate the size of the problem, this article ends with an interview question.

I hope that you will be inspired when you read this article. Although enumeration and union are rarely used at this stage, we must understand and realize that the content of the structure is very important. Self-reference Reasonable use will be frequently used in data structures! !

Finally, your comments, your likes and favorites are the driving force for Xiao Wang to move forward. Welcome to give advice. If there are any deficiencies, please point them out, thank you! ! !

Guess you like

Origin blog.csdn.net/qq_63319459/article/details/128674423