First, the declaration of the structure
1. Basic knowledge 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.
2. Declaration of the structure
struct tag//(tag is the tag of a structure) { member-list;//member variables of a structure }variable-list;//structure variable
Example: If we briefly describe a student's information
struct Stu { char name[20];//name int age;//age char sex[5];//gender char id[20];//student ID }; //Important: : The semicolon cannot be lost
Note:::** Here we find that this example of mine seems to be different from the statement we gave above. Is it because I wrote it wrong? ? ? **
In fact, it is because if the structure variable we create in the first way is a global variable, and if we want to use this structure in the second way, we need to create it in the main function, and we need to create the variable in the main function. Called a temporary variable, it is destroyed as soon as the braces of the main function are exited.
3. Special statement
Note: When declaring a structure, it can be incompletely declared.
E.g:
struct { int a; char b; float c; }x; struct { int a; char b; float c; }a[20], *p; int main() { p = &x; } //We found that the one thing missing from both structs is the label of our struct
We call such declarations anonymous struct declarations.
If you are given such a formula at this time, is it legal? ? ?
If we put it in the compiler to compile
We found that the compiler actually reported a warning
It says that the two types are incompatible, which is why the compiler will treat the above two declarations as two completely different types, so it is illegal.
Second, the structure of self-reference
Is it OK to have a member of type the struct itself in a struct?
struct Node { int data; struct Node next; }; //Is it feasible? //If so, what is sizeof(struct Node)?
The answer is no, because you think about if sizeof wanted to calculate its size, it would go all the way into struct Node like a loop.
The correct spelling should be
struct Node { int data; struct Node* next; };
let it find the address of the next struct, which can then be chained together
When you want to define a structure variable inside a function, we need to write like this
struct Node { int data; struct Node *next; }; int main() { struct Node s; return 0; }
So at this time, we think of custom types to reduce the length we write when defining structure variables.
typedef struct { int data; Node* next; }Node;//So we write
This is not acceptable, because here we are still using typedef to define the name of the structure.
//The correct way is typedef struct Node { int data; struct Node* next; }Node;
Note: Of course, we generally do not use custom types, because we may confuse the structure, and we don't know which structure type it is when we see the name.
3. Definition and initialization of structure variables
struct Point { int x; int y; }p1; //Declare the variable p1 while declaring the type int main() { struct Point p2; //Define the structure variable p2 struct Point p3 = {x, y};//Initialization: Assign an initial value while defining a variable. } struct Stu //type declaration { char name[15];//name int age; //age }; int main() { struct Stu s = {"zhangsan", 20};//initialization } struct Node { int data; struct Point p; struct Node* next; }n1 = {10, {4,5}, NULL}; //Structure nested initialization int main() { struct Node n2 = {20, {5, 6}, NULL};//Structure nested initialization }
Fourth, structure memory alignment
struct alignment rules
- The first member is at the address at offset 0 from the structure variable.
- Other member variables should be aligned to an address that is an integer multiple of a number (alignment number).
Note: Alignment = the smaller of the compiler's default alignment and the size of the member.
The default value in VS is 8 - The total size of the structure is an integer multiple of the maximum alignment (each member variable has an alignment).
- 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 multiple of all maximum alignment numbers (including the alignment number of nested structures).
//Exercise 1 struct S1 { char c1; int i; char c2; }; int main() { printf("%d\n", sizeof(struct S1)); }
According to the rules of alignment, the alignment of char type is 1, and the alignment of int type is 4
The offset (starting at 0) should be an integer multiple of the alignment number
The total size of the structure is an integer multiple of the maximum number of alignments (the maximum number of alignments is 4)
struct S2 { char c1; char c2; int i; }; int main() { printf("%d\n", sizeof(struct S2)); }
According to the rules of alignment, the alignment of char type is 1, and the alignment of int type is 4
The offset (starting at 0) should be an integer multiple of the alignment number
The total size of the structure is an integer multiple of the maximum number of alignments (the maximum number of alignments is 4)
Key point: Here we find that the two questions have the same data
However, we found that the result here is 8, this is because our storage order is not the same.
Note: Here we can find that the creation order of variables also affects its memory storage, so we can create variables appropriately and save space.
struct S3 { double d; char c; int i; }; int main() { printf("%d\n", sizeof(struct S3)); }
According to the alignment rules, the alignment of the char type is 1, the alignment of the int type is 4, and the alignment of the double type is 8.
The offset (starting at 0) should be an integer multiple of the alignment number
The total size of the structure is an integer multiple of the maximum number of alignments (the maximum number of alignments is 8)
struct S4 { char c1; struct S3 s3; double d; }; int main() { printf("%d\n", sizeof(struct S4)); }
According to the alignment rules, the alignment of the char type is 1, and the alignment of the double type is 8.
The offset (starting at 0) should be an integer multiple of the alignment number
The total size of the structure is an integer multiple of the maximum number of alignments (the maximum number of alignments is 8)
If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment number (the number of alignments is 8), and the overall size of the structure is the maximum number of alignments (including the alignment of nested structures). integer multiples of the number).
5. Modify the default alignment number
#include <stdio.h> #pragma pack(8)//Set the default alignment number to 8 struct S1 { char c1; int i; char c2; }; #pragma pack()//Unset the default alignment number, restore to default #pragma pack(1)//Set the default alignment number to 1 struct S2 { char c1; int i; char c2; }; #pragma pack()//Unset the default alignment number, restore to default int main() { //What is the result of the output? printf("%d\n", sizeof(struct S1)); printf("%d\n", sizeof(struct S2)); return 0; }
in conclusion:
When the alignment of the structure is not suitable, we can change the default alignment by ourselves.
Six, structure parameters
struct S { int data[1000]; int num; }; struct S s = {{1,2,3,4}, 1000}; //structure parameter void print1(struct S s) { printf("%d\n", s.num); } //Structure address parameter void print2(struct S* ps) { printf("%d\n", ps->num); } int main() { print1(s); //transfer structure print2(&s); //pass address return 0; }
The result we see here is the same, but in fact, the first method is not good in memory. We said before that the formal parameter is a temporary copy of the actual parameter. Since it is a copy, it will definitely occupy memory space.
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.
in conclusion:
When passing parameters to a structure, you need to pass the address of the structure.