C savior (structs, bit fields, enums, unions -- 12)

content

1. Structure

1.1 Declaration of Structure

1.2 Special declarations Anonymous structs

1.3 The self-referential typedef of a structure is type renaming

1.4 typedef type renaming

1.5 Definition and initialization of structure variables

1.6 Structure memory alignment Calculate the size of the structure

 1.7 Why does memory alignment exist?

 In general: The memory alignment of structures is the practice of exchanging space for time.

1.8 Modify the default alignment number

1.9 Structure parameter passing

2. Bit segment

The declaration and structure of bit fields are similar, with two differences:

1. The members of the bit field must be int, unsigned int or signed int, char

2. The member name of the bit field is followed by a colon and a number.

2.1 Memory allocation of bit segment

 2.2 Cross-Platform Issues with Bit Segments

2.3 Applications of Bit Segments 

3. Enumeration

3.1 Advantages of enumeration

4. Consortium (Union)

4.1 Using consortium to transform big and small end judgment

4.2 Calculation of joint size


1. Structure

1.1 Declaration of Structure

A structure is a collection of values ​​called member variables. Each member of the structure can be a variable of a different type.

struct tag
{
 member-list;
}variable-list;//变量列表,在这里创建的是全局变量

describe a student

struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}; //分号不能丢

1.2 Special declarations Anonymous structs

struct
{
	char name[20];
	char id[12];
}*ps;//必须在变量后加列表,只能使用一次

struct
{
 int a;
 char b;
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
}a[20], *p;


p = &x;//类型一样么?

Like anonymous structure members, they are also different types of structures in the eyes of the compiler

Role: The created structure is only used once, and anonymous structures can be used

1.3 Self-reference typedef of structure is type renaming

wrong self-reference

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

Correct self-reference: contains the next struct pointer

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

1.4 typedef type renaming

typedef struct Node
{
	int data;//数据
	struct Node* next;//指针
} Node,* pNode;

typedef对

//struct Node
//{
//	int data;//数据
//	struct Node* next;//指针
//};

类型重定义,取名为Node

pNode 等价--> struct Node*,对结构体指针重命名pNode,是一种指针类型

int main()
{
	struct Node n1;//两个类型相等
	Node n2;

	return 0;
}

1.5 Definition and initialization of structure variables

struct Book
{
	char name[20];
	float price;
	char id[12];
}s = { "投币", 55.5f, "PGC001" };

struct Node
{
	struct Book b;
	struct Node* next;
};

int main()
{
	struct Book s2 = { "点赞", 66.6f, "HG001" };
	struct Node n = { {"C语言拯救者", 66.8, "TG001"}, NULL };//结构体嵌套

	return 0;
}

1.6 Structure memory alignment Calculate the size of the structure

struct S1
{
	char c1;//1个字节
	int i;//4个字节
	char c2;//1个字节
};

struct S2
{
	char c1;//1
	char c2;//1
	int i;//4
};

int main()
{
	struct S1 s;
	struct S1 s2;
	printf("%d", sizeof(s));
	printf("%d", sizeof(s2));
	return 0;
}

The size of the s structure is 12 bytes, and the size of the s2 structure is 8 bytes, because the structure is memory aligned

Alignment rules for structures: 1. The first member is stored at an address with an offset of 0 from the structure variable.

2. Other member variables should be aligned to an address that is an integer multiple of a number (alignment number).

Alignment = the smaller of the compiler's default alignment and the size of the member.

The default alignment value in VS is 8; there is no default alignment number in the Linxu environment, and when there is no default alignment number, its own size is the alignment number

3. The total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).

4. If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment number, and the overall size of the structure is an integer of all maximum alignment numbers (including the alignment number of nested structures). times.


Let's actually illustrate the four rules with an example

struct S1
{
	char c1;//1个字节
	int i;//4个字节
	char c2;//1个字节
};

 

 another example

struct S2
{
	char c1;//1
	char c2;//1
	int i;//4
};

 

 

 s4 structure nesting problem, how big is s4?

struct S3
{
 double d;
 char c;
 int i;
};

struct S4
{
 char c1;
 struct S3 s3;
 double d;
};

 

 1.7 Why does memory alignment exist?

 In general: The memory alignment of structures is the practice of exchanging space for time.

1. Platform reasons (transplant reasons): 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 in order to access unaligned memory, the processor needs to make two memory accesses; aligned memory accesses require only one access .

When designing a structure, we must not only satisfy the alignment, but also save space. How to do it: Let the members that occupy the small space be concentrated as much as possible.

1.8 Modify the default alignment number

 The default alignment number of VS is 8, and it is best to modify the default alignment number to the power of 2

#pragma pack(1)//设置默认对齐数为1
struct S
{
	char c;//1
	double d;//8
};
#pragma pack()取消设置的默认对齐数,还原为默认

int main()
{
	struct S s;
	printf("%d\n", sizeof(s));//占9个字节
	return 0;
}

1.9 Structure parameter passing

When passing parameters to a function, the parameters need to be pushed onto the stack, which will result in system overhead in terms of time and space. If a structure object is passed, the structure is too large, and the system overhead of parameter stacking is relatively large, so the performance will be degraded.

struct S
{
 int data[1000];
 int num;
};
struct S s = {
   
   {1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
 printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
 printf("%d\n", ps->num);
}
int main()
{
 print1(s);  //传结构体
 print2(&s); //传地址
 return 0;
}

When passing parameters to a structure, you need to pass the address of the structure.


2. Bit segment

The declaration and structure of bit fields are similar, with two differences:

1. The members of the bit field must be int, unsigned int or signed int, char

2. The member name of the bit field is followed by a colon and a number.

Bit (binary bit),: The number represents the number of bits occupied

struct A
{
	int _a : 2;//_a这个成员只占2个bit位
	int _b : 5;//_b这个成员只占5个bit位
	int _c : 10;
	int _d : 30;
};


struct AA
{
	int _a;//INT_MIN ~ INT_MAX
	int _b;
	int _c;
	int _d;
};//16


//16位机器 - sizeof(int) - 2
//32/64位机器 - sizeof(int) - 4

int main()
{
	printf("%d\n", sizeof(struct A));//8
printf("%d\n", sizeof(struct AA));//16
	return 0;
}

Precautions:

1. The use of the bit segment is designed according to the needs. For example, if a member only expresses three states of 0 1 2 3, only 2 bits need to be allocated to save space.

2. The bit segment has no memory alignment, and the bit segment is a structure

2.1 Memory allocation of bit segment

1. The space of the bit segment is opened up in the form of 4 bytes ( int ) or 1 byte ( char ) as needed.

Not enough space to open up 1/4 byte space, not enough to continue to open up 1/4 byte space

2. Bit segment involves many uncertain factors. Bit segment is not cross-platform. Programs that focus on portability should avoid using bit segment or write cross-platform code.

3. The members of the bit field can be int unsigned int signed int or char (belonging to the integer family) type

struct A
{
	int _a : 2;//_a这个成员只占2个bit位
	int _b : 5;//_b这个成员只占5个bit位
	int _c : 10;
	int _d : 30;
};

 

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

int main()
{
	struct S s = { 0 };
	printf("%d\n", sizeof(s));

	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;

	return 0;
}

 2.2 Cross-Platform Issues with Bit Segments

1. It is uncertain whether an int bit field is treated as a signed or unsigned number.

2. The maximum number of bits in the bit segment cannot be determined. (16-bit machines have a maximum of 16, and 32-bit machines have a maximum of 32. If the int bit segment is written as 27, there will be problems on 16-bit machines.

3. Whether the members of the bit field are allocated in memory from left to right or from right to left is undefined.

4. When a structure contains two bit segments, and the members of the second bit segment are too large to accommodate the remaining bits of the first bit segment, it is uncertain whether to discard the remaining bits or use them.

2.3 Applications of Bit Segments 

 Data in the network transmission packaging: network protocol stack

3. Enumeration

Enumeration, as the name suggests, is an enumeration. List the possible values.

Monday to Sunday of the week is limited to 7 days, which can be listed one by one.

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

Gender: male, female, confidential...

enum Sex//枚举类型
{
	MALE,
	FEMALE,
	SECRET//{}中的内容是枚举类型的可能取值,也叫 枚举常量 。
};

int main()
{
	enum Sex s = MALE;//枚举类型变量赋值
	enum Sex s2 = FEMALE;//枚举的可能取值
	return 0;
}

These possible values ​​all have values. The default starts from 0 and increments by 1 at a time. Of course, an initial value can also be assigned when defining.

After the enumeration constant is assigned, according to the previous value + 1, the value cannot be changed outside the enumeration variable after the assignment

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

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

enum Color//颜色
{
 RED=22,
 GREEN=28,
 BLUE//29
};

RED = 6;//错误

3.1 Advantages of enumeration

1. Increase the readability and maintainability of the code

2. Compared with the identifier defined by #define, enumeration has type checking, which is more rigorous.

error in cpp

enum Color c = 5;//一个是枚举类型,一个是int类型

 

3. Prevents naming pollution (encapsulation)

4. It is easy to debug    (the replacement of #define definition symbols is to directly replace the defined symbols into the code)

5. Easy to use, you can define multiple constants at a time

4. Consortium (Union)

The union is also a special custom type. The variable defined by this type also contains a series of members, and the characteristic is that these members share the same space (so the union is also called a union) .

declaration of union type 

union Un
{
 char c;//1
 int i;//4
};

int main()
{
	union Un u;
	printf("%d\n", sizeof(u));
	printf("%p\n", &u);
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));
	return 0;
}

 Un occupies 4 bytes, and the three addresses of u, uc, and ui are exactly the same

 When we change i, the value of c will also be changed (members of the union will only use one at a time, not at the same time)

u.c = 0x55;
u.i = 0;

4.1 Using consortium to transform big and small end judgment

int check_sys()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i = 1;

	return u.c;//
}

int main()
{
	if (1 == check_sys())
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

 

4.2 Calculation of joint size

Calculation Rules:

The size of the union is at least the size of the largest member.

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.

 union Un1
{
	char arr[5];//5
	int i;//4
};

 union Un2
{
	short arr[7];//14 2
	int i;//4 4
};

int main()
{
	printf("%d\n", sizeof(union Un1));//8,进行了内存对齐
    printf("%d\n", sizeof(union Un2));//16,看数组成员而不是数组
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_63543274/article/details/124048637