content
Definition and initialization of structure variables
1. Structure objects. Structure members
2. Structure pointer -> structure member
Why does memory alignment exist?
Memory allocation for bit fields
Cross-platform issues with bit fields
Definition of enumeration types
Advantages of enumeration types
1. Structure
Why is there a structure?
The data types we learned earlier: char, int, double, and pointers are not enough to represent objects . If we want to represent a person, can we use a number to represent it? It is definitely not possible. It is necessary to know that people are complex objects and cannot be simply represented by a certain number. To represent a person, many aspects are needed, such as name, gender, age, etc. To represent people, we have to create a complex type, and there is a struct type in C language
Structure is a particularly important knowledge point in C language. Structure enables C language to describe complex types.
The structure type also needs to be created by the word
struct declaration
Basic knowledge of structure
A struct is a collection of values called member variables, each member of the struct can be a variable of a different type
struct declaration
Describe a person:
Way 1:
struct Peo //声明了一个结构体类型
{
char name[20];
int age;
};
This is the declaration of the structure, struct is the structure keyword, Peo is the structure label (structure type name), and the curly brackets are the structure member variables
Structure members can be scalars, arrays, pointers, structures
Way 2:
struct Peo
{
char name[20];
int age;
}p1, p2 //全局变量
Method 2 is to create two structure variables of type struct Peo when the structure is declared, but it should be noted that p1 and p2 obtained by this creation method are global variables with a wide scope, which is generally not recommended. Write
Mode 3 (anonymous struct type)
struct
{
char name[20];
int age;
}p1, p2;
struct
{
char name[20];
int age;
}p1;
struct
{
char name[20];
int age;
}*p;
The first code directly omits the structure label (structure type name), so that the p1 and p2 structure variables can only be created after the structure is created, and cannot be created in the following main function. Relatively limited, not recommended
The second code creates a pointer p later, but if on the basis of the second code, it is illegal to write p = &p1; below, and the compiler will treat the above two declarations as two completely different types . So it's illegal
Self-referencing of structs
When we use the structure, can we write the structure in the structure when declaring the structure
The following code:
struct Peo
{
char name[20];
int age;
struct Peo next;
};
It should be noted that this is not acceptable, because if it is written like this, what should be the size of the structure? I'm sure it won't come out
Correct spelling
struct Peo
{
int data;
struct Peo* next;
};
Put a structure pointer of the same type in the structure
Definition and initialization of structure variables
How to define structure variables, see the following code:
Code 1:
#include <stdio.h>
#include <string.h>
struct Peo
{
char name[20];
int age;
};
int main()
{
struct Peo p = { "张三",18 }; //通过结构体类型来创建结构体变量并初始化
printf("%s %d\n", p.name, p.age);
//修改里面的内容
strcpy(p.name, "李四");
p.age = 20;
printf("%s %d\n", p.name, p.age);
return 0;
}
Through this code, a structure describing a person is created and initialized, and the content in it is modified later
analogy:
In fact, using a structure is equivalent to building a house. The previous statement of the structure is the drawing of the drawing, and the later creation of the structure variable is to build the house according to the drawing.
So when we declare a structure, the system will not allocate space to it. Only after the structure variable is created will the system allocate space to it.
Code 2 (create a global structure variable)
struct Peo
{
char name[20];
int age;
}p1,p2,p3;
When the structure is declared, write the name/label of the structure variable to be created directly after the curly braces, but it should be noted that the global variable is created here. It is recommended to use this method less.
access to structure members
1. Structure objects . Structure members
The following code accesses the structure members through the structure variable name/label
struct Peo
{
char name[20];
int age;
};
int main()
{
struct Peo p = { "张三",18 };
printf("%s %d\n", p.name, p.age);
return 0;
}
operation result:
2. Structure pointer -> structure member
The following code: Access structure members through structure pointers
#include <stdio.h>
struct Peo
{
char name[20];
int age;
};
int main()
{
struct Peo p = { "张三",18 };
struct Peo* ps = &p;
printf("%s %d\n", ps->name, ps->age);
return 0;
}
operation result:
structure parameter
Structure parameter transfer is divided into value transfer and address transfer
1. Pass by value
The following code:
struct Peo
{
char name[20];
int age;
};
void print1(struct Peo p)
{
printf("%s %d\n", p.name, p.age);
}
int main()
{
struct Peo p = { "张三",18 };
print1(p); //传值,传整个结构体过去
return 0;
}
This is to pass the entire structure directly
2. Address
struct Peo
{
char name[20];
int age;
};
void print2(struct Peo* ps)
{
printf("%s %d\n", ps->name, ps->age);
}
int main()
{
struct Peo p = { "张三",18 };
print2(&p);
return 0;
}
Pass the address of the structure
For these two parameter passing methods, we prefer the second method
The reason is:
When passing parameters to a function, the parameters need to be pushed onto the stack. If a structure object is passed, the structure is too large, and the system overhead of parameter stacking is relatively large, so it will lead to performance degradation.
Structure memory alignment
If we want to calculate the memory size of a structure, how do we calculate it? Is it to add the memory size of all member variables directly?
First look at the following code:
#include <stdio.h>
struct P
{
char a;
int b;
};
int main()
{
struct P p;
printf("%d\n", sizeof(p));
}
After creating the structure variable p here, find the size of this structure, is it 1+4==5?
operation result:
The print result is 8, which obviously shows that the size of the structure is not a simple addition of member variables, so how did this 8 come from? This involves structure memory alignment
Alignment rules
- The first member is at the address at offset 0 from the struct variable (offset 0 from the starting position)
- The remaining other member variables should be aligned to an integer multiple of a certain number (alignment number)
- Alignment : The smaller of the size of each member itself and the default alignment of the compiler used
- The total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number)
- 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).
Tip: The default alignment number of the VS compiler is 8, and the gcc compiler under linux has no default alignment number
Then you can now use the alignment rules to find the size of the structure
In the above code, the first one in the structure is of type char, which is placed directly at offset 0
The second type is int type, its own size is 4, and the default alignment number is 8, so the alignment number takes the smaller value of 4
The total size of the structure is an integer multiple of the maximum alignment number
See by drawing
So the size of this structure is 8
Why does memory alignment exist?
- Platform reason (transplantation 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
- 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.
So structure memory alignment is to trade space for time
When designing the structure, we must not only satisfy the alignment, but also save space, so that the members that occupy the small space should be concentrated as much as possible.
Modify the default alignment
Just now we said that the default alignment number of the VS compiler is 8, but in fact this default alignment number can be modified
When the alignment of the structure is not suitable, we can change the default alignment by ourselves
#pragma pack() //括号内放想达到的默认对齐数
The following code:
#include <stdio.h>
#pragma pack(4) //修改默认对齐数为4
struct P
{
char a;
int b;
};
#pragma pack() //取消设置的默认对齐数,还原为默认值
int main()
{
struct P p;
printf("%d\n", sizeof(p));
}
Note: This default alignment number cannot be modified at will, and the modified value must be 2^n (n==0,1,2,3...)
Second, the segment
What is a bit segment
C language allows to specify the length of memory occupied by its members in units of bits in a structure . Such members in units of bits are called "bit fields" or " bit fields ". Use bit fields to store data with fewer bits
as follows:
struct A
{
int a : 2;
int b : 3;
int c : 5;
int d : 10;
};
It can be seen from the code that the declaration of the bit field is very similar to the structure. The number after the colon indicates the size of the member (in bits). There are two differences:
- The members of the bit field must be int, unsigned int, or signed int
- Bit fields have a colon and a number after the member name
So what is the size of this bit segment? Is it 2+3+5+10 bits? Definitely not, test it with code
struct A
{
int a : 2;
int b : 3;
int c : 30;
int d : 10;
};
int main()
{
printf("%d\n", sizeof(struct A));
return 0;
}
operation result:
So how does this 12byte come from? Next, look at the memory allocation of the bit segment
Memory allocation for bit fields
- The members of the bit field can be of type int unsigned int signed int or char (belonging to the integer family)
- The space of the bit field is opened up in the form of 4 bytes ( int ) or 1 byte ( char ) as needed
- Bit segment involves many uncertain factors, bit segment is not cross-platform, and programs that focus on portability should avoid using bit segment
There are 4 variables of type int in the declaration of the bit segment in the preceding code, which should have taken up 16 bytes of space, but only 12 bytes are occupied after the bit segment is used. The calculation method is as follows:
When the requested memory is not enough, and the second bit segment member is too large to fit in the remaining bits of the first bit segment, it is uncertain whether to discard the remaining bits or use them, which depends on the compiler.
Cross-platform issues with bit fields
- It is indeterminate whether the int bit field is treated as signed or unsigned
- The maximum number of bits in the bit field cannot be determined. (16-bit machine is up to 16, 32-bit machine is up to 32, written as 27, there will be problems on 16-bit machines
- Whether members in a bit field are allocated in memory from left to right or from right to left is undefined
- When a structure contains two bit segments, and the second bit segment member is too large to fit in the remaining bits of the first bit segment, it is uncertain whether to discard the remaining bits or use them
Application of Bit Segments
When we usually want to send a hello message to a friend, we not only send hello, but also send hello and other data together, such as who sent the message, to whom, and the target ip address Information, etc., but some of these information may only need a few bits to save, it would be too wasteful to use all int, which will also affect the network condition, in this case, use the bit segment
3. Enumeration constants
What is an enumeration?
Enumeration means enumerating one by one, enumerating all possible values.
For example, colors, weeks, and months can all be listed. In C language, the values of a certain type we want are defined as enumeration types, and their values can also be listed one by one.
Definition of enumeration types
For example, now list the three primary colors
enum Color
{
RED,
GREEN,
BLUE
};
The content in {} is the possible value of the enumeration type, also called the enumeration constant
What is the value?
So what are the values here? The following code:
enum Color
{
RED = 3,
GREEN = 7,
BLUE = 5
};
int main()
{
printf("%d\n", RED);
printf("%d\n", GREEN);
printf("%d\n", BLUE);
}
print result:
These possible values all have values, starting from 0 by default and incrementing by 1 at a time. Of course, the initial value can also be assigned when defining . as follows:
enum Color { RED = 3, GREEN = 7, BLUE = 5 };
It can be used like this :
enum Color
{
RED ,
GREEN,
BLUE
};
int main()
{
enum Color c = RED;
}
Advantages of enumeration types
- Increase code readability and maintainability
- Enumerations are type-checked and more rigorous compared to identifiers defined by #define .
- Prevents naming pollution (encapsulation)
- easy to debug
- Easy to use, you can define multiple constants at a time
4. Union (community)
Definition of Union Types
Union is also a special custom type. Variables defined by this type also contain a series of members, characterized by the fact that these members share the same space (so union is also called union)
declaration of union type
The following code:
union U
{
char i;
int a;
};
So what is the size of the union here ?
It is also the principle of alignment, slightly different
The members of the union share the same memory space, so the size of such a union variable is at least the size of the largest member (because the union must at least be able to save the largest member)
The overall size is an integer multiple of the maximum number of alignments
-----------------------------------------------------------------
-------------The storage of C language floating point numbers in memory is completed---------
Regarding the C language, each knowledge point will be written in a separate blog for a more detailed introduction.
Welcome everyone to pay attention! ! !
Learn to communicate together! ! !
Let's get programming to the end! ! !
--------------It's not easy to organize, please support three consecutive -------------------