[Structure - Enumeration - Union]

Preface

This sharing is basic knowledge, I hope it can help everyone review the knowledge.

Structure

Declaration of structure type

  • Basics of structures
    A structure is a collection of values ​​calledMember variables. Each member of the structure can be a variable of different types.
  • Declaration of structure
    Form:

struct tag
{
member-list;
}variable-list;

For example, describe a student:

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

When declaring a structure, you can declare it incompletely.

for example:

//匿名结构体类型
struct
{
    
    
 int a;
 char b;
 float c;
}x;
struct
{
    
    
 int a;
 char b;
 float c;
}a[20], *p;

When the above two structures are declared,The structure tag is omitted.
Did the problem come?

//在上面代码的基础上,下面的代码合法吗?
p = &x;

warn:

The compiler will treat the above two declarations as two completely different types.
So it isUnlawful

self-referencing of structures

Is it okay to include a member in a structure that is of type the structure itself?

//代码1
struct Node
{
    
    
 int data;
 struct Node next;
};
//可行否?
如果可以,那sizeof(struct Node)是多少?

In fact, it is not feasible.

Correct way to self-reference:

//代码2
struct Node
{
    
    
 int data;
 struct Node* next;
};

Notice:

//代码3
typedef struct
{
    
    
 int data;
 Node* next;
}Node;
//这样写代码,可行否?
//解决方案:
typedef struct Node
{
    
    
 int data;
 struct Node* next;
}Node;

Definition and initialization of structure variables

With the structure type, how to define variables is actually very simple.

struct Point
{
    
    
 int x;
 int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {
    
    x, y};
struct Stu        //类型声明
{
    
    
 char name[15];//名字
 int age;      //年龄
};
struct Stu s = {
    
    "zhangsan", 20};//初始化
struct Node
{
    
    
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {
    
    10, {
    
    4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {
    
    20, {
    
    5, 6}, NULL};//结构体嵌套初始化

Structure memory alignment

We have mastered the basic use of structures.
Now let’s discuss a problem in depth: calculating the size of a structure.

This is also a particularly popular test point: structure memory alignment

//练习1
struct S1
{
    
    
 char c1;
 int i;
 char c2;
};
printf("%d\n", sizeof(struct S1));
//练习2
struct S2
{
    
    
 char c1;
 char c2;
 int i;
};
printf("%d\n", sizeof(struct S2));
//练习3
struct S3
{
    
    
 double d;
 char c;
 int i;
};
printf("%d\n", sizeof(struct S3));
//练习4-结构体嵌套问题
struct S4
{
    
    
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\n", sizeof(struct s4));

Test point: How to calculate?
First, you must master the alignment rules of the structure

1. The first member is at the address offset 0 from the structure variable.
2. Other member variables should be aligned to addresses that are integer multiples of a certain number (alignment number).
Alignment number = The smaller of the compiler's default alignment number and the size of the member.
The default value in VS is 8
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 the structure is nested, the nested structure is aligned to an integer multiple of its maximum alignment number, and the integer
of the structure The body size is an integer multiple of the maximum alignment number (including the alignment number of nested structures).

Why does memory alignment exist?
Most of the reference materials say this:
1. Platform reasons (transplantation 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 access requires only one access. Generally speaking: The memory alignment of structures is to trade space for time. When designing the structure, we must not only satisfy the alignment, but also save space. How to do it: Let the members that occupy less space be concentrated as much as possible Together.








//例如:
struct S1
{
    
    
 char c1;
 int i;
 char c2;
};
struct S2
{
    
    
 char c1;
 char c2;
 int i;
};

Members of types S1 and S2 are exactly the same, butThere are some differences in the size of the space occupied by S1 and S2.

Modify the default alignment number

We have seen the #pragma preprocessing directive before, and here we use it again to change our default alignment number.

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
    
    
 char c1;
 int i;
 char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
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;
}

in conclusion:

When the alignment of the structure is inappropriate, can we change the default alignment number ourselves?

Structure parameter passing

Go directly to the code:

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;
}

Which of the above print1 or print2 functions is better?

The answer is: the print2 function is preferred.

reason:

When the function passes parameters, the parameters need to be pushed onto the stack, which will cause system overhead in time and space.
If a structure object is passed and the structure is too large, the system overhead of pushing parameters onto the stack will be relatively large, which will lead to
performance degradation.

in conclusion:

When passing parameters of a structure, the address of the structure must be passed.

Structure implements bit fields (filling of bit fields & portability)

After talking about structures, we have to talk about the ability of structures to realize bit segments.

  • What is a bit field
    The declaration and structure of a bit field are similar, with two differences:
    1. The members of a 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.

    For example:
struct A
{
    
    
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

A is a bit segment type.
What is the size of segment A?

printf("%d\n", sizeof(struct A))

The answer is: 8

  • Memory allocation of bit segment
    1. Members of bit segment can be int unsigned int signed int or char (belonging to the integer family) type
    2. The space of the bit field is allocated in 4 bytes (int) or 1 byte (char) as needed.
    3. Bit segments involve many uncertain factors. Bit segments are not cross-platform. Programs that focus on portability should avoid using bit segments.
//一个例子
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;
//空间是如何开辟的?

Insert image description here

  • Cross-platform issues with bit fields
    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 the bit field cannot be determined. (A 16-bit machine has a maximum of 16, a 32-bit machine has a maximum of 32, which is written as 27. This will cause problems on a 16-bit machine.
    3. Are the members in the bit segment allocated from left to right in the memory? The right-to-left allocation standard has not been defined.
    4. When a structure contains two bit fields, the members of the second bit field are larger and cannot fit in the remaining bits of the first bit field. , it is uncertain whether to discard the remaining bits or use them.

Summarize:
Compared with the structure, the bit segment can achieve the same effect, but can save space very well, but there are cross-platform problems.

enumerate

Enumeration, as the name suggests, means enumerating items one by one.
List the possible values ​​one by one.
For example, in our real life:
There are a limited number of 7 days from Monday to Sunday in a week, and they can be listed one by one.
Gender includes: male, female, confidential, you can also list them one by one.
There are 12 months in the month, you can also list them one by one

Definition of enumeration type

enum Day//星期
{
    
    
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
enum Sex//性别
{
    
    
 MALE,
 FEMALE,
 SECRET
}enum Color//颜色
{
    
    
 RED,
 GREEN,
 BLUE
};

The enum Day , enum Sex , and enum Color defined above are all enumeration types.
The contents in {} are possible values ​​of the enumeration type, also called enumeration constants.
These possible values ​​are all valid. By default, they start from 0 and increase by 1 at a time. Of course, an initial value can also be assigned when defining.
For example:

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

Advantages of enumerations

Why use enumerations?
We can use #define to define constants, why do we have to use enumerations?
Advantages of enumerations:
1. Increase the readability and maintainability of the code
2. Compared with identifiers defined by #define, enumerations have type checking, which is more rigorous.
3. Prevents naming pollution (encapsulation)
4. Easy to debug
5. Easy to use, multiple definitions can be defined at one time constant

Use of enumerations

enum Color//颜色
{
    
    
 RED=1,
 GREEN=2,
 BLUE=4
};
enum Color clr = GREEN;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。

Union (community)

union type definition

United alsois a special custom type
Variables defined in this type also contain a series of members. The characteristic is that these members share the same space (so a union is also called a union).
For example:

//联合类型的声明
union Un
{
    
    
 char c;
 int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));

Features of the union

The members of a union share the same memory space, so the size of a union variable must be at least the size of the largest member (because the union must be able to store at least the largest member).

union Un
{
    
    
 int i;
 char c;
};
union Un un;
// 下面输出的结果是一样的吗?
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
//下面输出的结果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);

Union size calculation

UnitedThe size 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.
For example:

union Un1
{
    
    
 char c[5];
 int i;
};
union Un2
{
    
    
 short c[7];
 int i;
};
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));

The answer is: 8,16

Okay, this sharing ends here. These are some class notes from a novice. The content is relatively basic. I hope you can support me a lot. And if there are any mistakes, I hope you can correct me. Thank you all!

Guess you like

Origin blog.csdn.net/weixin_73807021/article/details/129731845