1, Structure
1.1 basic knowledge of structure
Definition: a structure is a collection of values called member variables. Each member of the structure can be a different type of variable.
1.2 declaration of structure
Syntax:
struct tag { member-list; }variable-list;//Variable list can be omitted
1.3 special declaration
When declaring a structure, you can declare it incompletely
//Anonymous structure type struct { int a; char b; float c; }x;
🔵 Features: can only be used once.
🔴 be careful:
struct { int a; char b; float c; }x; struct { int a; char b; float c; }a[20], * p; int main() { //p = &x;// The err compiler treats the two declarations as different types return 0; }
1.4 self reference of structure
If a structure of the same type is also defined inside the structure, the value of sizeof (structure) will be infinite. To solve the above problem, we can define pointers to structures of the same type.
struct Node//node { int data;//Data domain struct Node* next;//Pointer field };
🔴 Note: do not be anonymous when the structure is self referenced
typedef struct { int data; //Node* next;// The err anonymous structure is called node only after it is named, but it is obviously wrong to use node in the declaration }Node;
1.5 definition, initialization and access of structure variables
struct book { char name[20]; char author[20]; int price; }b1 = { "xxx","xxx",12 };//Creation and initialization of global variables struct book b2 = { "xxx","xxx",12 };//Creation and initialization of global variables //There are structures in the structure struct S { int x; struct book b4; }; int main() { struct book b3 = { "xxx","xxx",12 };//Creation and initialization of local variables struct S s = { 1,{"xxx","xxx",12} };//The structure body contains the creation and initialization of the structure body printf("%d\n", b1.price); printf("%s\n", s.b4.author); return 0; }
1.6 structure memory alignment
struct S1 { char c1; int i; char c2; }; struct S2 { char c1; char c2; int i; }; struct S3 { double d; char c; int i; }; //Structure nesting problem struct S4 { char c1; struct S3 s3; double d; }; int main() { printf("%d\n", sizeof(struct S1));//? printf("%d\n", sizeof(struct S2));//? printf("%d\n", sizeof(struct S3));//? printf("%d\n", sizeof(struct S4));//? }
Rules for structure memory alignment:
① The first member of the structure is always placed at the beginning of the structure with an offset of 0.
② Structure members start with the second member and are always placed at an offset of an integer multiple of the alignment number. (alignment number: the smaller value between the compiler's default alignment number and the size of the variable itself. There is no default alignment number in Linux, and the default alignment number in VS is 8)
③ The total size of the structure must be an integral multiple of the largest number of alignments of each member.
④ Nesting exists. If a structure is nested, the nested structure is aligned to an integer multiple of its maximum alignment number, and the overall size of the structure is an integer multiple of all the maximum alignment numbers (including the alignment number of nested structures)
🔴 Note: the declaration of structure type does not occupy memory space. Only after the variable is created can the memory space be opened up
❗ Why memory alignment exists:
✅
① Platform reason (migration reason): not all hardware platforms can access any data at any address; Some hardware platforms can only get certain types of data at certain addresses, otherwise hardware exceptions will be thrown.
② Performance reason: data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that in order to access misaligned memory, the processor needs to make two memory accesses; Aligned memory access requires only one access.
Summary: the memory alignment of structures is to exchange space for time.
Therefore, when designing the structure, we should not only meet the alignment, but also save space, so that the members with small space can be concentrated together as much as possible.
1.7 modify the default alignment number
When the alignment of the structure is inappropriate, we can change the default alignment number ourselves# The pragma preprocessing instruction can change our default alignment number.
#pragma pack(8) / / set the default alignment number to 8 struct S1 { char c1;// 1 8 1 int i; // 4 8 4 char c2;// 1 8 1 }s1; #pragma pack() / / unset the default alignment number and restore it to the default (8 in VS) #pragma pack(1) / / set the default alignment number to 1 struct S2 { char c1;//1 1 1 int i; //4 1 1 char c2;//1 1 1 }s2; #pragma pack() / / unset the default alignment number and restore it to the default int main() { printf("%d\n", sizeof(s1));//12 printf("%d", sizeof(s2));//6 }
[supplementary reading]: Implementation of offsetof macro: calculate the offset of a variable in the structure relative to the first address
1.8 structural transmission parameters
There are two methods to transmit: ① transmit structure ② transmit address
struct S { int data[1000]; int num; }; struct S s = { {1,2,3,4}, 1000 }; //Structural transmission parameters void print1(struct S s) { for (int i = 0; i < 4; i++) { printf("%d", s.data[i]); } printf("\n"); printf("%d\n", s.num); } //Structure address transfer parameter void print2(struct S* ps) { for (int i = 0; i < 4; i++) { printf("%d", ps->data[i]); } printf("\n"); printf("%d\n", ps->num); } int main() { print1(s); //Transmission structure print2(&s); //Transmission address return 0; }
🔴 Note: when transferring parameters to a function, the parameters need to be pressed on the stack, which will have system overhead in time and space.
If the structure is too large when passing a structure object, it will lead to performance degradation. Therefore, it is best to use the way of address transmission.
If you are afraid that the pointer will modify the data inside the structure, the solution can be protected with const
//The structure address is passed to const protection void print2(const struct S* ps) { for (int i = 0; i < 4; i++) { printf("%d", ps->data[i]); } printf("\n"); printf("%d\n", ps->num); }
2, Enumeration
2.1 definition of enumeration type
🔵 characteristic:
① The constants inside {} are called enumeration constants
(constants include const modified constant variables, #define defined identifier constants, and enumeration constants)
② By default, it starts from 0 and increments by 1
enum Day//week { Mon, //be careful! The tail is, Tues, Wed, Thur, Fri, Sat, Sun }; int main() { printf("%d\n", Mon);//0 printf("%d\n", Tues);//1 return 0; }
//assignment enum Color//colour { RED = 1, GREEN = 2, BLUE = 4 }; int main() { printf("%d\n", RED);//1 printf("%d\n", BLUE);//4 }
2.2 advantages of enumeration
① Increase the readability and maintainability of the code
② Compared with #define defined identifiers, enumeration has type checking, which is more rigorous# Define is a direct replacement, while enumeration is reserved.
③ Prevents naming contamination (encapsulation)
④ Easy to use, you can define multiple constants at a time
2.3 use of enumeration
enum Color//colour { RED = 1, GREEN = 2, BLUE = 4 }; int main() { //In c + +, it is not considered that enum and int types do not match // //enum Color c1 = 2; //if (c1 == GREEN) //{ // printf("green"); //} enum Color c2 = GREEN; if (c2 == GREEN) { printf("green"); } }
3, United
3.1 definition of association type
🔵 Features: members share the same space
//Declaration of union type union Un { char c;//1 int i;//4 }; //Definition of joint variables union Un un; //Verify common space int main() { printf("%p\n", &un); //000DA13C printf("%p\n", &(un.c)); //000DA13C printf("%p\n", &(un.i)); //000DA13C }
3.2 large and small end of consortium test
int check() { union UN { int i; char c; }un; un.i = 1; return un.c; } int main() { if (1 == check()) { printf("Small end storage mode"); } else { printf("Big end storage mode"); } }
3.3 calculation of joint size
Calculation rule of union size:
① Union members share the same memory space, so the size of a union variable 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 should be aligned to an integer multiple of the maximum alignment number.
//eg1 union Un { char c;//1 8 1 int i; //4 8 4 }; union Un un; int main() { printf("%d\n", sizeof(un));//4 }
//eg2 union Un1 { char c[5];//1 8 1 int i; //4 8 4 }; union Un2 { short c[7];//2 8 2 int i; //4 8 4 }; int main() { printf("%d\n", sizeof(union Un1));//Not 5, but 8 printf("%d\n", sizeof(union Un2));// 7 16 }