[C language] Custom types: structure, enumeration, union


1. Structure

1.1 What is a structure

A structure is a collection of values ​​called member variables, which can be of different types.

1.2 Declaration of structure

struct stu//标签/类型名
{
	char name[20];//成员变量
	int age;//成员变量
};//分号不能丢

结构体的特殊声明

struct     //没有标签
{
	char name[20];
	int age;
}s1;//s1是在声明时定义的全局变量
  1. The above structure declaration is called an anonymous structure type, that is, it has no name.
  2. This type can only create variables directly at creation time.insert image description here
  3. Since there is no name, is the following code legal?
struct
{
	int a;
	char b;
	float c;
}x;
struct
{
	int a;
	char b;
	float c;
}a[20], * p;
int main()
{
	p = &x;
	return 0;
}

Incorrect. The structure type pointed to by p is already different from the structure type of x. insert image description here
That is to say, this anonymous structure type can only be used once, and when you use it again, it will be a different type.

1.3 Self-reference of structure

Which of the following two approaches is correct?

struct Node
{
	int data;
	struct Node next;
};

struct Node
{
	int data;
	struct Node* next;
};

At first glance, it seems to be all right, but if the size of the structure is required, there is a loophole. The first way is wrong, because it refers to itself, infinite nesting dolls, and the size cannot be obtained, while the second way uses pointers of the same type to point to the next structure and store the address of the next structure, so The data can be concatenated.

1.4 Definition and initialization of structure variables

struct stu
{
	char name[20];
	int age;
}s1;//这是在声明的同时定义的变量(全局变量)
struct stu s2;//这是结构体的定义
struct people
{
	struct stu p;
	char sex[5];
	float score;
};
int main()
{
	struct stu s3;//这是在函数内定义的局部变量
	struct stu s4 = { "zhangsan",20 };//这是结构体的初始化
	struct stu s5 = { .age = 20,.name = "zhangsan" };//这是结构体的乱序初始化
	printf("%s %d\n", s5.name, s5.age);//这是结构体的打印
	struct people s6 = { {"lisi",19},"nan",99.5f };//结构体的嵌套初始化
	printf("%s %d %s %f\n", s6.p.name, s6.p.age, s6.sex, s6.score);
}

Results
zhangsan 20
lisi 19 nan 99.500000

注意

typedef struct stu
{
	char name[20];
	int age;
}Stu;//Stu不是变量,而是重命名的类型
int main()
{
	Stu s = { "zhangsan",20 };
	return 0;
}

1.5 Memory alignment of structures

Let's first guess the size of the following two structures

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));
}

Results
12
8

疑惑
Why are there two different results? Isn't it the size of two char plus an int, a total of 6 bytes?
This is related to the memory alignment of the structure. Instead of simply arranging its own size for continuous storage, there are certain alignment rules.
对齐规则

  1. The first member of the structure is aligned to offset 0 where the structure is stored in memory. Take struct S1 s as an example.
    insert image description here

  2. Starting with the second member, each member is aligned to an integer multiple of an alignment number. Alignment: The smaller value of the structure member's own size and the default alignment . The default alignment number of VS is 8, and Linux gcc has no alignment number, and the alignment number is the size of the structure member itself. Take struct S1 s as an example, the size of i is 4, the default alignment number is 8, and the alignment number is 4. To align to an integer multiple of 4, the size of c2 is 1, the default alignment number is 8, and the alignment number is 1. Align to an integer multiple of 1.
    insert image description here

  3. The structure size must be an integer multiple of the largest alignment among all members. Take struct S1 s as an example. During the current calculation process, the size of the structure is 9 bytes, and the maximum alignment among all members is 4. 9 is not a multiple of 4, so it continues to occupy space.

insert image description here
We can use the offsetof function to verify this alignment rule. offsetof returns the offset, the first parameter is the type name, the second parameter is the member name, and the header file is stddef.h.

struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};
int main()
{
	struct S1 s;
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	printf("%d\n",offsetof(struct S1,c1));
	printf("%d\n",offsetof(struct S1 ,i));
	printf("%d\n",offsetof(struct S1, c2));
}

Result
12
8
0
4
8

  1. If there is a nested structure in the structure, the nested structure should be aligned to an integer multiple of the maximum alignment number of its own members. The total size of the structure must be an integer multiple of the maximum alignment, where the maximum alignment is the maximum value of all alignments including the alignments in the members of the nested structure.
//练习
struct S3
{
	char c1;
	int i;
	char c2;
}s3;
struct S4
{
	char c;
	struct S3 s3;
	double d;
}s4;

The maximum alignment number of s3 is 4, and must be aligned to an integer multiple of 4. The alignment number of double is 8, and it must be aligned to an integer multiple of 8.insert image description here
练习

struct S3
{
double d;
char c;
int i;
};
struct S2
{
char c1;
char c2;
int i;
};
  1. Through the calculations of the above exercises, when designing the structure, if we want to satisfy the alignment and save space, let the members that occupy a small space be gathered together as much as possible.
  2. If the structure member contains an array, how to align and store it? Think of arrays as different variables of the same type, for example, char a[3] sees char a1, char a2, and char a3.

为什么会存在结构体对齐
from online references

  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 is 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.
    insert image description here

1.6 Modify the default alignment number

#pragma pack(1)//设置默认对齐数为1
struct S
{
	char c1;
	int i;
	char c2;
};
#pragma pack(1)//设置默认对齐数为1
int main()
{
	struct S s;
	printf("%d", sizeof(s));
	return 0;
}

result
6

When the alignment of the structure is not suitable, we can modify the default alignment.

1.7 Structure parameter passing

Function parameter passing includes value passing and address passing. Which method is better for structures? first look at the example

struct stu
{
	char name[20];
	int age;
};
void print1(struct stu s)
{
	printf("%s ", s.name);
	printf("%d\n", s.age);
}
void print2(struct stu* s)
{
	printf("%s ", s->name );
	printf("%d\n", s->age );
}
int main()
{
	struct stu s = { "zhangsan",20 };
	print1(s);
	print2(&s);
	return 0;
}

When a function passes parameters, it needs to open up space for the formal parameters on the stack area. If the formal parameters are too large, the more space needs to be opened up, and the more time and space the function needs to spend during execution. Passing the structure itself as a parameter may need to open up a large area of ​​space. If it is passed as a pointer, the space opened up is much smaller.
结论
Therefore, when the structure is passed as a parameter, the address of the structure must be passed.


2. Bit segment

2.1 What is a bit segment

A bit segment is a special structure, but it has two differences from the structure: one is that the members of the bit segment must be int, unsigned int, signed int or char; the second is that there is a colon after the member name of the bit segment and a number.

struct S//S就是一个位段
{
	int a : 2;
	int b : 4;
	int c : 10;
	int d : 20;
};

So what's the meaning of the colon and the number after it? What is the size of the bit segment? Will the bitfields be aligned, or is there some other way of storing them? Take your time.
(1) The colon and the following number indicate how many bits this member variable occupies, for example, a occupies two bits, b occupies 4 bits, and c occupies 10 bits. And this number cannot exceed the size of the member itself, the char type cannot exceed 8, and the int type cannot exceed 32.
(2) The result of sizeof(struct S) is 8, why is it 8? This involves memory allocation for bit segments.

2.2 Memory allocation for bit segments

例子

struct S
{
char a:3;
char b:4;
char c:5;
char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

How is space allocated?

  1. The first member a of the structure is of char type, which opens up an 8-bit space. Assign 10 to a, first convert 10 to binary, since a occupies 3 bits, so the binary of 10 is truncated, and the last 3 bits are given to a, and placed on the right side of the space.insert image description here
  2. b occupies 4 bits of the remaining space, truncates the binary number of 12, and puts it into these 4 bits according to the above method.insert image description here
  3. c occupies 5 bits, and only 1 bit is left in the opened space, so one byte of space is re-applied to the memory. The remaining 1 bit in the old space is discarded, and 5 bits are occupied in the new space. The remaining steps will not be described in detail. insert image description here
    The result size is 3 bytes. Through this example, we can also understand the storage method of the bit segment. And it seems to be more space-saving than the structural body segment, but the bit segment involves many uncertain factors, the bit segment is not cross-platform, and the program that pays attention to portability should avoid using the bit segment.

2.3 Cross-platform problems of bit segment

  1. It is undefined whether an int bit field is treated as signed or unsigned.
  2. The maximum number of bits in a bit field cannot be determined. (16-bit machines have a maximum of 16, 32-bit machines have a maximum of 32, written as 27, and there will be problems on 16-bit machines. For example, on some machines, the size of int is 32 bits, and on other machines it may be 16 bits, which may be unintentional. beyond its own size.
  3. Whether members of a bit field are allocated from left to right in memory or from right to left is undefined. The example I gave is based on the VS compiler, and its members are allocated from right to left in memory.
  4. When a structure contains two bit fields, and the members of the second bit field are too large to accommodate the remaining bits of the first bit field, it is uncertain whether to discard or utilize the remaining bits. In the VS compiler, if the remaining space is not enough to accommodate the next bit field, it will be discarded.

3. Enumeration

3.1 What is an enumeration

Enumeration, as the name suggests, is to enumerate one by one, and enumerate the possible values ​​one by one. For example, subjects, relatives, and months can all be listed one by one.

3.2 Declaration of enumeration

enum Sex//枚举类型
{
	MALE,//枚举常量
	FEMALE,//枚举常量
	SECRET,//枚举常量
};//这些枚举常量是枚举的可能取值
int main()
{
	enum Sex s = MALE;//s是基于枚举类型创建的变量,其可能取值只能是上面3个
	return 0;
}

These possible values ​​increase from top to bottom, and from top to bottom when they are not initialized, starting from 0 and adding 1 in turn.insert image description here

3.3 Advantages of enumeration

  1. Increase the readability and maintainability of the code. Use enumerations to give meaning to some values, such as gender, which is not directly expressed in numbers, but in English to increase its readability; when these enumeration constants need to be modified, they only need to be modified at their declarations, without Look for it deliberately to increase maintainability.
  2. Compared with the identifier defined by #define, the enumeration has type checking, which is more rigorous.
  3. Prevents naming pollution (encapsulation). Enums group these constants together.
  4. Easy to debug. Constants defined by #define cannot be debugged, because the constants have been swapped during debugging.
  5. Easy to use, multiple constants can be defined at one time.

3.4 The size of the enumeration

insert image description here
Why 4? A variable of an enumeration type can only be one of the constants, and these constants are integers, so their size is an integer (4).

4. Consortium (community)

4.1 What is a consortium

A union is also a collection of some values, which are also its members, but its characteristic is that these members share a piece of memory, so it is also called a union.

4.2 Definition of Consortium

union UN//联合体的声明
{
	char c;
	int i;
};
int main()
{
	union UN u;//联合体的定义
	printf("%d",sizeof(u));
	return 0;
}

result
4

疑惑
Why 4?
We can check the addresses of the member variables of the union, and we insert image description here
can find that the addresses are the same, which also verifies that the members of the union share a piece of memory, indicating that the size of the union is at least the size of the largest member, so that other members can be accommodated. This means that two variables cannot be used at the same time without conflict. These variables do not need to exist at the same time, which also saves space to a certain extent.
insert image description here

练习
In the section on data storage , there is a written test question: judge the size and size of the current computer. Now introduce another approach.

union UN
{
	char c;
	int i;
};
int main()
{
	union UN un;
	un.i = 1;
	if (un.c == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

insert image description here

4.3 Calculate the size of the union

  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, it must be aligned to an integer multiple of the maximum alignment.
    例子
union Un1
{
	char c[5];//最大成员大小是5
	int i;//最大对齐数是4
};
union Un2
{
	short c[7];//最大成员的大小是14
	int i;//最大对齐数是4
};
printf("%d",sizeof(union Un1));//8
printf("%d",sizeof(union Un2));//16

Guess you like

Origin blog.csdn.net/Zhuang_N/article/details/128841326