Detailed explanation of C language custom types (nanny-level teaching)

Table of contents

1. Structure

1.1 Introduction to structures

1.2 Declaration of structure

1.3 Special declaration (anonymous structure type)

1.4 Structure self-reference

1.5 Definition and initialization of structure variables

1.6 Structure memory alignment

1.7 Modify the default pair number

2. Bit segment

2.1 What is a bit segment?

2. Memory allocation for 2-bit segments

3. Enumeration

3.1 Definition of enumeration

3.2 Advantages of enumeration

4.Consortium (Commonwealth)

4.1 Definition of union type

4.2 Characteristics of the consortium

 4.3 Calculation of consortium size


What is a custom type?

In C language, we can use structures, enumerations, and unions to create custom types.

1. Structure

1.1 Introduction to structures

Struct: A structure is a user-defined data type used to combine different types of data to form a new composite type. A structure consists of a set of members, each member can be a different data type, such as integer, character, floating point, pointer, etc. A structure is defined using  struct keywords and then specifies the name of the structure and the list of members.

1.2 Declaration of structure

struct student
{
	char name[20];
	int age;
	char sex[5];
	char id[20]
};

In the above code, we define a structure named student, which contains an array of integer types and three character types.

1.3 Special declaration (anonymous structure type)

struct
{
	int a;
	float b;
	float c;
}x;

In the above code, the struct tag is omitted - this is the anonymous struct type.

1.4 Structure self-reference

We can include a structure in a structure. If the included structure is the structure pointer of the structure itself, it is a self-reference of the structure.

struct student
{
	int age;
	char name[20];
	struct student* s1;
};

1.5 Definition and initialization of structure variables

struct student
{
	int age;
	char name[20];
}s1,s2;//在声明结构体类型时定义变量s1,s2

struct student s3;//定义结构体变量s3


struct point
{
	int x;
	int y;
}p1={1,1};//结构体嵌套初始化


struct point p2 = { 1,2 };//初始化

1.6 Structure memory alignment

Structure memory alignment is used to calculate the size of the structure

How to calculate?

First, you must master the alignment rules of the structure:
1. The first member is at the address with an offset of 0 from the structure variable.
2. Other member variables should be aligned to an address that is an integer multiple 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.
There is no default alignment number in Linux. The alignment number is the size of the member itself. 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 and the nested structure is aligned to an integer multiple of its own maximum alignment number, the
overall is the sum of all maximum alignment numbers (including the alignment number of the nested structure) Integer multiple
.

Example:

struct S1
{
	char c1;
	int i;
	char c2;
};
int main()
{
	printf("%d \n", sizeof(struct S1));
	return 0;
}

 

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 access any data on certain addresses. Get certain
types of data at the address, 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 unaligned memory, the processor needs to make two memory accesses; aligned memory access requires only one access
.

Generally speaking:
memory alignment of structures is a way of exchanging space for time.

1.7 Modify the default pair number

#pragma pack(1)//设置默认对齐数为1
struct S3
{
	double d;
	char c;
	int i;
};
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
#pragma pack ()//取消设置默认对齐数,还原为默认

2. Bit segment

2.1 What is a bit segment?

Bit fields (Bitfields) are a technology used in C language to define structure members. It allows us to control the data in the structure at the bit level.

The purpose of the bit field is to store the data of each field (or bit) in the structure member and utilize less memory space. Often, using full bytes or larger data types can be a waste of memory when dealing with some smaller range of integer values.

The declaration of bit fields is similar to that of structures, with two differences:

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.

for example:

struct student
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

student is a bit segment type. What about the size of the student?

2. Memory allocation for 2-bit segments

1. The members of the bit field can be int unsigned int signed int or char (belonging to the integer family) type
2. The space of the bit field is 4 bytes (int) or 1 byte (char) as needed To open up.
3. Bit segments involve many uncertain factors. Bit segments are not cross-platform. Programs that focus on portability should avoid using bit segments.

Example:

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;

3. Enumeration

3.1 Definition of enumeration

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 valuable, starting from 0 by default and increasing by 1 in sequence. Of course, an initial value can also be assigned when declaring the enumeration type.
For example:

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

3.2 Advantages of enumeration

Why use enumerations?
We can use #define to define constants, why do we have to use enumerations?
Advantages of enumerations:
1. Increases code readability and maintainability
2. Compared with identifiers defined by #define, enumerations have type checking and are more rigorous.
3. Easy to debug
4. Easy to use, multiple constants can be defined at one time

4.Consortium (Commonwealth)

A union is a special data type that allows different types of data to be stored in the same memory location. Unlike a structure, each member of a union shares the same memory space.

4.1 Definition of union type

//联合体类型的声明
union Un
{
	char c;
	int i;
};

int main()
{
	//联合体变量的定义
	union Un un;
	//计算联合体变量的大小
	printf("%d\n", sizeof(un));
	//打印结果为4
}

4.2 Characteristics of the consortium

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 save at least the largest member).

union Un

{
	int i;
	char c;
};
int main()
{
	union Un un;
	printf("%d \n", &(un.i));
	printf("%d \n", &(un.c));

	un.i = 1;
	un.c = 2;
	printf("%d \n", un.i);
	return 0;
}

 Example: Determine the big and small endianness of the current machine?

int Pd()
{
	union
	{
		int i;
		char c;
	}un = { .i = 1 };
	return un.c;
}
int main()

{
	int ret = Pd();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

 4.3 Calculation of consortium size

The size of the union 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.

Guess you like

Origin blog.csdn.net/qq_55119554/article/details/131729754