C language - custom type structure_study notes

Basic concepts of structures

A structure is a user-defined data type that can containMultiple variables of different types. By using structures, we can organize related data together for easy management and use.

Structure declaration

Normal structure declaration

In C language, structure (struct) refers to a data structure, which is a type of aggregate data type in C language.
A structure can contain multiple data members of different types, such as int, float, char, etc.

The structure is declared as follows:

struct 结构体名 {
    
    
    类型1 数据成员1;
    类型2 数据成员2;
    ...
    类型n 数据成员n;
};

For example:

struct student {
    
    
    int id;
    char name[50];
    int age;
};                  //注意,结构体定义后面的分号不要忘了

The above is a normal structure declaration ↑↑↑↑↑↑↑↑↑↑↑↑

Anonymous structure declaration

Since there are normal ones, there are special structure declarations ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
When declaring a structure, it can be incompletely declared. (Anonymous structure type)
as follows:

//匿名结构体类型
struct
{
    
    
	int a;
	char b;
	float c;
}x;
struct 
{
    
    
	int a;
	char b;
	float c;
}*p;
  • p is a structure pointer. As you can see here, the member contents of the upper and lower structures are exactly the same.
  • Can p = &xthis be achieved?
  • The answer is no, the compiler will treat the above two declarations as completely different structure types, so p cannot put the address of x! ! !

The above two structures omit the structure tag when declaring it, so it is okay to declare it this way, but! Anonymous structure types can only define structure variables when they are created. If the structure type is not renamed, it can basically only be used once.

typedef structure alias

You can use the typedef keyword to alias the structure, so that some structure names with long names can be simplified, which is more convenient when we need to create structure variables frequently.
For example:

#include <stdio.h>

struct Chinese_Student {
    
    
    char name[50];
    int age;
    float score;
};

typedef struct Chinese_Student Student; // 为结构体起别名Student

int main() {
    
    
    Student stu = {
    
    "Tom", 20, 88.5}; // 创建并初始化结构体变量,其实就等价于Chinese_Student stu = {"Tom", 20, 88.5};
    printf("Name: %s\n", stu.name); // 访问结构体变量的成员
    printf("Age: %d\n", stu.age);
    printf("Score: %.1f\n", stu.score);
    return 0;
}

Self-referencing of structures

Is it okay to include a member in a structure that is of type the structure itself?
For example, the following code:

struct Node
{
    
    
	int data;
	struct Node next;
};                      //error报错

This code will report an error because the structure contains structures of the same type as members, so the size of the structure variables will be infinite, which is unreasonable.

The correct way to self-reference a structure, use a structure pointer

struct Node
{
    
    
	int data;
	struct Node* next;
};  

Creation and initialization of structure variables

For the creation and initialization of structure variables, use sample code to illustrate:

#include <stdio.h>

//创建结构体变量前,要先对结构体进行声明↓↓↓↓↓↓
struct student {
    
    
    char name[50];  //这里声明一个student类型的结构体,有三个成员
    int age;        //分别是字符类型姓名,整型类型年龄,浮点型类型分数
    float score;
};

int main() {
    
    
   
    // 可以在创建结构体变量的时候同时按声明中的结构体成员顺序对结构体变量进行初始化操作↓↓
    struct student stu1 = {
    
    "Tom", 20, 88.5}; 
    
    //也可以用成员访问操作符,不按照成员顺序对结构体成员进行初始化操作↓↓↓↓↓
    struct student stu2 = {
    
    .age=18, .name="weil", .score=99.9}; 
    
	// 访问结构体变量的成员↓↓↓↓↓↓↓
    printf("Name: %s\n", stu2.name); 
    printf("Age: %d\n", stu2.age);
    printf("Score: %.1f\n", stu2.score);
    return 0;
}

Structure memory alignment

For the size of the structure, we can use the sizeof operator to calculate
as follows:

struct S1
{
    
    
	char c1;       //1字节
	int i;         //4字节
	char c2;       //1字节
};
int main()
{
    
    
	printf("%zd\n", sizeof(struct S1));
	return 0;
}

The running result is:
Insert image description here
Why is the number of bytes occupied by the structure of the above code 12 bytes?

This involves knowledge points about structure memory alignment↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

Structure memory alignment rules

  1. The first member of the structure is aligned to an address offset 0 relative to the starting position of 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 value of the compiler's default alignment number and the size of the member variable.
    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.
  3. The total size of the structure is an integer multiple of the maximum alignment number (each member variable in the structure has an alignment number, the largest of all alignment numbers).
  4. If a structure is nested, the members of the nested structure are aligned to an integer multiple of the maximum alignment number of its own members, and the overall size of the structure is the maximum alignment number of all members (including the alignment number of the members in the nested structure). ) is an integer multiple.

Why does memory alignment exist?

Most of the references 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 whenever 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.

Assuming a processor always fetches 8 bytes from memory, the address must be a multiple of 8. If we can ensure that the addresses of all double type data are aligned to multiples of 8, then we can use a memory operation to read or write the value. Otherwise, we may need to perform two memory accesses because the object may be divided into two 8-byte memory blocks.

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

Explain with examples

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

The above code running results (VS 2022):
Insert image description here
The member types in the structure are the same, and different arrangement orders will also affect the size of the structure variables. This is the secret of structure memory alignment. Next, draw a memory layout diagram to explain:
Insert image description here

When designing the structure, we must not only meet the alignment requirements, but also save space. We must gather members that occupy as little space as possible together.

Structure array

↓↓↓↓↓↓↓↓↓↓↓↓↓Create structure array & traverse to access structure array↓↓↓↓↓↓↓↓↓↓↓↓↓
The code example is as follows:

#include <stdio.h>

// 定义一个结构体类型
struct Student {
    
    
    char name[20];
    int age;
    float score;
};

int main() {
    
    
    // 创建结构体数组并初始化
    struct Student students[] = {
    
    
        {
    
    "Tom", 20, 88.5},
        {
    
    "Jack", 21, 92.0},
        {
    
    "Alice", 19, 95.5}
    };

    // 遍历访问打印结构体数组中的所有内容
    int len = sizeof(students) / sizeof(struct Student);  // 计算数组长度
    for (int i = 0; i < len; i++) {
    
    
        printf("Name: %s\n", students[i].name);
        printf("Age: %d\n", students[i].age);
        printf("Score: %.1f\n", students[i].score);
    }

    return 0;
}

In this example, we first define a structure type named Student, which contains three member variables: name, age and score. Then, we created a structure array students of type Student in the main function and initialized the elements in it. Next, we use a for loop to iterate through each element in the array and use the printf function to print out each student's name, age, and score.

When accessing the elements of the structure array, we use the structure variable name plus the index to access. For example, students[i].name means accessing the name member variable of the i-th element.

Structure pointer

↓↓↓↓↓↓↓↓↓↓↓↓↓Creation & initialization & member access of structure pointers↓↓↓↓↓↓↓↓↓↓↓↓↓

#include <stdio.h>

// 定义一个结构体类型
struct Student {
    
    
    char name[20];
    int age;
    float score;
};

int main() {
    
    
    // 创建结构体变量并初始化
    struct Student stu1 = {
    
    "Tom", 20, 88.5};
    struct Student stu2 = {
    
    "Jack", 21, 92.0};
    struct Student stu3 = {
    
    "Alice", 19, 95.5};

    // 创建结构体指针变量
    struct Student *stuPtr;

    // 将结构体变量的地址赋给结构体指针变量
    stuPtr = &stu1;

    // 遍历打印结构体指针中的内容
    printf("Name: %s\n", stuPtr->name);
    printf("Age: %d\n", stuPtr->age);
    printf("Score: %.1f\n", stuPtr->score);

    // 将结构体指针变量指向下一个结构体变量
    stuPtr = &stu2;

    // 遍历打印结构体指针中的内容
    printf("Name: %s\n", stuPtr->name);
    printf("Age: %d\n", stuPtr->age);
    printf("Score: %.1f\n", stuPtr->score);

    // 将结构体指针变量指向下一个结构体变量
    stuPtr = &stu3;

    // 遍历打印结构体指针中的内容
    printf("Name: %s\n", stuPtr->name);
    printf("Age: %d\n", stuPtr->age);
    printf("Score: %.1f\n", stuPtr->score);

    return 0;
}

In this example, we first define a Student structure type, which contains the student's name, age and score. In the main function, we create three structure variables of Student type and initialize them respectively.

Then, we 创建了一个Student类型的指针变量stuPtruse to point to these structure variables. We assign the address of the first structure variable to stuPtr, access ->运算符the data in the structure through pointers, and print out the student's information. Then, we point the pointer variable to the next structure variable and repeat the above operation until all structure variables have been traversed.

Guess you like

Origin blog.csdn.net/yjagks/article/details/132950395