Table of contents
2.11 Basic knowledge of structure
2.12 Structure memory alignment (a popular test point)
Structure memory alignment rules:
2.13 Why do we need structure memory alignment?
2.14 Modify the default alignment number
2.15 Function parameter passing
2.17 Cross-platform problems in bit segments
2. 21 Advantages of Enumeration
I. Introduction
In this section, we will share the knowledge of structures, enumerations, and associations with our friends, hoping to bring benefits to our friends.
2. Text
2.1 Structure
2.11 Basic knowledge of structure
struct tag{member - list ;} variable - list ;
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};//分号不能丢
//匿名结构体类型
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], *p;
It is worth noting that the anonymous structure is only valid for the variables at the time of creation, such as: x, a[20], *p are anonymous, and the anonymous structure cannot be used to create a new structure variable later.
2.12 Structure memory alignment (a popular test point)
Next, let's take a closer look: structure memory size
//计算出结构体内存大小
struct S1
{
char c1; //1字节
int i; // 4字节
char c2; // 1字节
};
// 结果: 12个字节
Why is this?
Let's find out here
Structure memory alignment rules:
- 1. The first member is at the address whose offset from the structure variable is 0 .
- 2. Other member variables should be aligned to an address that is an integer multiple of a certain number (alignment number) .
Alignment = Compiler's default alignment and the smaller value of the member size .The default value in VS is 8, and the default alignment number of linux is itself, such as: int alignment number is 4
- 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 is equal to the maximum alignment number (including the alignment number of the nested structure) Integer multiples.
Here we analyze the previous example:
How to detect it?
Here I will introduce a macro-offsetof, whose function is to return the offset of the memory where the structure member is located .
Header file: #include<stddef.h>
use:
#include<stddef.h>
#include<stdio.h>
struct S3
{
double d;// 对齐数 8
char c; // 对齐数1
int i; // 对齐数4
}s3;
int main()
{
printf("%u\n", offsetof(struct S4, c1)); // 0
printf("%u\n", offsetof(struct S4, s3)); // 8
printf("%u\n", offsetof(struct S4, d)); // 12
return 0;
}
The above example only practices the first three principles. Let's take another example of nested structures:
//练习4-结构体嵌套问题
struct S3
{
double d; // 对齐数 8
char c; // 对齐数1
int i; // 对齐数4
};
// S3 的大小: 16个字节
struct S4
{
char c1;
struct S3 s3; // 对齐数 8 , 16字节
double d; // 对齐数8
};
printf("%d\n", sizeof(struct S4));
// 结果: 32
2.13 Why do we need structure memory alignment?
Much of it is explained this way:
- 1. Platform reason ( transplant reason ) :
Not all hardware platforms can access arbitrary 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 in order to access unalignedmemory, the processor requires two memory accesses; aligned memory accesses require only one access.In general:The memory alignment of the structure is the practice of exchanging space for time .
So how do we reduce space usage?
Let members who occupy a small space gather together as much as possible.
2.14 Modify the default alignment number
like:
#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
char c1; // 1 8 -> 1
int i; // 4 8-> 4
char c2; // 1 8-> 1
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1) //设置默认对齐数为8
struct S2
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{
//输出的结果是什么?
printf("%d\n", sizeof(struct S1));
printf("%d\n", sizeof(struct S2));
return 0;
}
It is worth noting that the default alignment number modified by #pragma pack() is generally 2 ^ n, and there are rarely odd numbers.
2.15 Function parameter passing
2.16 bit segments
1. The members of the bit field must be int , unsigned int or signed int .2. There is a colon and a number after the member name of the bit field, indicating the occupied bit.
struct A
{
int _a:2; // 2 bit
int _b:5; // 5bit
int _c:10;
int _d:30;
}; // 问那 struct A的大小是多少?结果是 8个字节
//一个例子
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;
//空间是如何开辟的?
Parse:
Idea: First, when a byte is full or not enough, create another byte space.
Here we need to distinguish from the previous big and small endian byte order. This time, the moving unit is bit, and the latter unit is byte.
2.17 Cross-platform problems in bit segments
1. It is uncertain whether the int bit field is regarded as a signed number or an unsigned number .2. The maximum number of bits in a bit field cannot be determined. ( Maximum 16 for 16 -bit machines , maximum 32 for 32 -bit machines , written as 27 , there will be problems in 16 -bit machines.3. Whether the members in the bit segment are allocated from left to right in memory or from right to left has not yet been defined.4. When a structure contains two bit segments, and the second bit segment is too large to accommodate the remaining bits of the first bit segment, it is uncertain whether to discard or utilize the remaining bits.
2.2 Enumeration
It is to list the possible results of a certain situation together, and when using it, directly use the data that is correct for the situation.
like:
12 months can be one, one list
Gender can also be listed one by one
Use as follows:
enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};
enum a
{
c, // 默认值为 0
b, // 1
k = 200, //赋值为200
z, // 由前+ 1,为 201
t // 同理 202
};
2. 21 Advantages of Enumeration
- Why use enums?
- 1. Increase the readability and maintainability of the code (less #define)
- 2. Compared with the identifier defined by #define , the enumeration has type checking , which is more rigorous.
(In c++, when enumeration constants are assigned, the data on the right side will be enumerated to determine whether it is an enumeration member)
- 3. Prevent naming pollution (the scope can be limited by enumeration name to avoid renaming)
- 4. Easy to debug (you can debug and find the corresponding value, unlike the #define definition, which is replaced during precompilation, and it is not easy to trace the source)
- 5. Easy to use, multiple constants can be defined at a time
2.3 Consortia
#include<stdio.h>
union p1
{
char i;
int z;
}a;
int main()
{
printf("%p\n", &(a.i));
printf("%p\n", &(a.z));
return 0;
}
result:
- The memory size of the union should also follow the structure memory alignment principle.
#include<stdio.h>
union p1
{
char i;
int z;
}a;
int main()
{
a.i = 5;
a.z = 1;
a.i == 1 ? printf("小端") : printf("大端");
return 0;
}
The result is little endian, using char i can only read the first byte of data, it can be judged that the value modified by int z exists in the first byte, so the machine is little endian.
3. Conclusion
This section ends here, thank you friends for browsing, if you have any suggestions, please comment in the comment area.