结构体

深入理解结构体

结构体是C语言中最重要的构造类型之一,它允许我们将不同类型的数据组合成一个有机整体。东巴文(db-w.cn) 将带你深入理解结构体的原理与实践。

💡 东巴文观点:结构体是C语言处理复杂数据的核心工具,掌握结构体是成为高级C程序员的必经之路。

什么是结构体

结构体的定义

#include <stdio.h>

void structDefinition() {
    printf("=== 东巴文结构体的定义 ===\n\n");
    
    printf("结构体:\n");
    printf("  一种用户自定义的数据类型\n");
    printf("  可以包含多个不同类型的成员\n");
    printf("  用于表示复杂的数据结构\n\n");
    
    printf("结构体的特点:\n");
    printf("  1. 成员可以是不同类型\n");
    printf("  2. 成员按顺序存储\n");
    printf("  3. 每个成员独立存储\n");
    printf("  4. 可以嵌套使用\n");
    printf("  5. 可以作为函数参数\n");
}

int main() {
    structDefinition();
    return 0;
}

结构体的声明

#include <stdio.h>
#include <string.h>

// 方式1:先定义结构体类型,再声明变量
struct Student1 {
    char name[50];
    int age;
    float score;
};

// 方式2:定义结构体类型的同时声明变量
struct Student2 {
    char name[50];
    int age;
    float score;
} stu1, stu2;

// 方式3:匿名结构体
struct {
    char name[50];
    int age;
} stu3;

// 方式4:使用typedef
typedef struct {
    char name[50];
    int age;
    float score;
} Student3;

void structDeclaration() {
    printf("=== 东巴文结构体的声明 ===\n\n");
    
    struct Student1 student1;
    Student3 student2;
    
    strcpy(student1.name, "东巴文");
    student1.age = 20;
    student1.score = 95.5;
    
    strcpy(student2.name, "db-w.cn");
    student2.age = 21;
    student2.score = 90.0;
    
    printf("student1: %s, %d岁, 成绩%.1f\n", 
           student1.name, student1.age, student1.score);
    printf("student2: %s, %d岁, 成绩%.1f\n", 
           student2.name, student2.age, student2.score);
}

int main() {
    structDeclaration();
    return 0;
}

结构体的初始化

初始化方式

#include <stdio.h>
#include <string.h>

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

void structInitialization() {
    printf("=== 东巴文结构体的初始化 ===\n\n");
    
    // 方式1:逐个成员赋值
    Student stu1;
    strcpy(stu1.name, "张三");
    stu1.age = 20;
    stu1.score = 85.5;
    
    // 方式2:声明时初始化
    Student stu2 = {"李四", 21, 90.0};
    
    // 方式3:指定成员初始化(C99)
    Student stu3 = {
        .name = "王五",
        .age = 22,
        .score = 88.5
    };
    
    // 方式4:部分初始化
    Student stu4 = {"赵六"};
    // age和score自动初始化为0
    
    printf("stu1: %s, %d岁, 成绩%.1f\n", stu1.name, stu1.age, stu1.score);
    printf("stu2: %s, %d岁, 成绩%.1f\n", stu2.name, stu2.age, stu2.score);
    printf("stu3: %s, %d岁, 成绩%.1f\n", stu3.name, stu3.age, stu3.score);
    printf("stu4: %s, %d岁, 成绩%.1f\n", stu4.name, stu4.age, stu4.score);
}

int main() {
    structInitialization();
    return 0;
}

结构体数组初始化

#include <stdio.h>

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

void structArrayInitialization() {
    printf("=== 东巴文结构体数组初始化 ===\n\n");
    
    Student students[3] = {
        {"张三", 20, 85.5},
        {"李四", 21, 90.0},
        {"王五", 22, 88.5}
    };
    
    printf("学生信息:\n");
    for (int i = 0; i < 3; i++) {
        printf("学生%d: %s, %d岁, 成绩%.1f\n", 
               i + 1, students[i].name, students[i].age, students[i].score);
    }
}

int main() {
    structArrayInitialization();
    return 0;
}

结构体成员访问

点运算符

#include <stdio.h>
#include <string.h>

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

void dotOperator() {
    printf("=== 东巴文点运算符 ===\n\n");
    
    Student student;
    
    // 使用点运算符访问成员
    strcpy(student.name, "东巴文");
    student.age = 20;
    student.score = 95.5;
    
    printf("使用点运算符访问:\n");
    printf("  姓名:%s\n", student.name);
    printf("  年龄:%d\n", student.age);
    printf("  成绩:%.1f\n", student.score);
}

int main() {
    dotOperator();
    return 0;
}

箭头运算符

#include <stdio.h>
#include <string.h>

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

void arrowOperator() {
    printf("=== 东巴文箭头运算符 ===\n\n");
    
    Student student;
    Student *ptr = &student;
    
    // 使用箭头运算符访问成员
    strcpy(ptr->name, "东巴文");
    ptr->age = 20;
    ptr->score = 95.5;
    
    printf("使用箭头运算符访问:\n");
    printf("  姓名:%s\n", ptr->name);
    printf("  年龄:%d\n", ptr->age);
    printf("  成绩:%.1f\n", ptr->score);
    
    printf("\n等价于:\n");
    printf("  ptr->name 等价于 (*ptr).name\n");
    printf("  ptr->age 等价于 (*ptr).age\n");
    printf("  ptr->score 等价于 (*ptr).score\n");
}

int main() {
    arrowOperator();
    return 0;
}

结构体与函数

结构体作为函数参数

#include <stdio.h>
#include <string.h>

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

// 值传递
void printStudent(Student stu) {
    printf("值传递:\n");
    printf("  姓名:%s\n", stu.name);
    printf("  年龄:%d\n", stu.age);
    printf("  成绩:%.1f\n", stu.score);
}

// 指针传递
void updateStudent(Student *stu, int newAge, float newScore) {
    stu->age = newAge;
    stu->score = newScore;
}

void structAsParameter() {
    printf("=== 东巴文结构体作为函数参数 ===\n\n");
    
    Student student = {"东巴文", 20, 95.5};
    
    printStudent(student);
    
    printf("\n修改前:\n");
    printf("  年龄:%d\n", student.age);
    printf("  成绩:%.1f\n", student.score);
    
    updateStudent(&student, 21, 98.0);
    
    printf("\n修改后:\n");
    printf("  年龄:%d\n", student.age);
    printf("  成绩:%.1f\n", student.score);
}

int main() {
    structAsParameter();
    return 0;
}

结构体作为返回值

#include <stdio.h>
#include <string.h>

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

Student createStudent(const char *name, int age, float score) {
    Student stu;
    strcpy(stu.name, name);
    stu.age = age;
    stu.score = score;
    return stu;
}

void structAsReturnValue() {
    printf("=== 东巴文结构体作为返回值 ===\n\n");
    
    Student student = createStudent("东巴文", 20, 95.5);
    
    printf("创建的学生:\n");
    printf("  姓名:%s\n", student.name);
    printf("  年龄:%d\n", student.age);
    printf("  成绩:%.1f\n", student.score);
}

int main() {
    structAsReturnValue();
    return 0;
}

结构体数组

结构体数组的定义

#include <stdio.h>
#include <string.h>

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

void structArray() {
    printf("=== 东巴文结构体数组 ===\n\n");
    
    Student students[3];
    
    // 初始化
    for (int i = 0; i < 3; i++) {
        sprintf(students[i].name, "学生%d", i + 1);
        students[i].age = 20 + i;
        students[i].score = 80.0 + i * 5;
    }
    
    // 输出
    printf("学生信息:\n");
    for (int i = 0; i < 3; i++) {
        printf("学生%d: %s, %d岁, 成绩%.1f\n", 
               i + 1, students[i].name, students[i].age, students[i].score);
    }
}

int main() {
    structArray();
    return 0;
}

结构体数组的排序

#include <stdio.h>
#include <string.h>

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

void sortStudents(Student students[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (students[j].score < students[j + 1].score) {
                Student temp = students[j];
                students[j] = students[j + 1];
                students[j + 1] = temp;
            }
        }
    }
}

void structArraySorting() {
    printf("=== 东巴文结构体数组的排序 ===\n\n");
    
    Student students[5] = {
        {"张三", 20, 85.5},
        {"李四", 21, 90.0},
        {"王五", 22, 88.5},
        {"赵六", 20, 92.0},
        {"钱七", 21, 87.0}
    };
    
    printf("排序前:\n");
    for (int i = 0; i < 5; i++) {
        printf("%s: %.1f\n", students[i].name, students[i].score);
    }
    
    sortStudents(students, 5);
    
    printf("\n排序后(按成绩降序):\n");
    for (int i = 0; i < 5; i++) {
        printf("%s: %.1f\n", students[i].name, students[i].score);
    }
}

int main() {
    structArraySorting();
    return 0;
}

结构体指针

结构体指针的定义

#include <stdio.h>
#include <string.h>

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

void structPointer() {
    printf("=== 东巴文结构体指针 ===\n\n");
    
    Student student = {"东巴文", 20, 95.5};
    Student *ptr = &student;
    
    printf("使用指针访问:\n");
    printf("  姓名:%s\n", ptr->name);
    printf("  年龄:%d\n", ptr->age);
    printf("  成绩:%.1f\n", ptr->score);
    
    printf("\n指针大小:%zu字节\n", sizeof(ptr));
    printf("结构体大小:%zu字节\n", sizeof(Student));
}

int main() {
    structPointer();
    return 0;
}

结构体指针数组

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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

void structPointerArray() {
    printf("=== 东巴文结构体指针数组 ===\n\n");
    
    Student *students[3];
    
    // 动态分配
    for (int i = 0; i < 3; i++) {
        students[i] = (Student *)malloc(sizeof(Student));
        sprintf(students[i]->name, "学生%d", i + 1);
        students[i]->age = 20 + i;
        students[i]->score = 80.0 + i * 5;
    }
    
    printf("学生信息:\n");
    for (int i = 0; i < 3; i++) {
        printf("学生%d: %s, %d岁, 成绩%.1f\n", 
               i + 1, students[i]->name, students[i]->age, students[i]->score);
    }
    
    // 释放内存
    for (int i = 0; i < 3; i++) {
        free(students[i]);
    }
}

int main() {
    structPointerArray();
    return 0;
}

结构体的嵌套

结构体嵌套结构体

#include <stdio.h>
#include <string.h>

typedef struct {
    int year;
    int month;
    int day;
} Date;

typedef struct {
    char name[50];
    Date birthday;
    float score;
} Student;

void nestedStruct() {
    printf("=== 东巴文结构体嵌套结构体 ===\n\n");
    
    Student student;
    
    strcpy(student.name, "东巴文");
    student.birthday.year = 2000;
    student.birthday.month = 1;
    student.birthday.day = 1;
    student.score = 95.5;
    
    printf("学生信息:\n");
    printf("  姓名:%s\n", student.name);
    printf("  生日:%d-%02d-%02d\n", 
           student.birthday.year, 
           student.birthday.month, 
           student.birthday.day);
    printf("  成绩:%.1f\n", student.score);
}

int main() {
    nestedStruct();
    return 0;
}

结构体嵌套数组

#include <stdio.h>
#include <string.h>

typedef struct {
    char course[50];
    float score;
} CourseScore;

typedef struct {
    char name[50];
    CourseScore courses[3];
    float average;
} StudentRecord;

void nestedArray() {
    printf("=== 东巴文结构体嵌套数组 ===\n\n");
    
    StudentRecord student;
    
    strcpy(student.name, "东巴文");
    
    strcpy(student.courses[0].course, "数学");
    student.courses[0].score = 95.0;
    
    strcpy(student.courses[1].course, "英语");
    student.courses[1].score = 88.5;
    
    strcpy(student.courses[2].course, "物理");
    student.courses[2].score = 92.0;
    
    student.average = (student.courses[0].score + 
                       student.courses[1].score + 
                       student.courses[2].score) / 3;
    
    printf("学生成绩单:\n");
    printf("  姓名:%s\n", student.name);
    printf("  各科成绩:\n");
    for (int i = 0; i < 3; i++) {
        printf("    %s: %.1f\n", student.courses[i].course, student.courses[i].score);
    }
    printf("  平均分:%.1f\n", student.average);
}

int main() {
    nestedArray();
    return 0;
}

内存对齐

内存对齐的概念

#include <stdio.h>

typedef struct {
    char a;
    int b;
    char c;
} Struct1;

typedef struct {
    int b;
    char a;
    char c;
} Struct2;

void memoryAlignment() {
    printf("=== 东巴文内存对齐 ===\n\n");
    
    printf("Struct1布局:\n");
    printf("  char a (1字节) + 填充 (3字节) + int b (4字节) + char c (1字节) + 填充 (3字节)\n");
    printf("  总大小:%zu字节\n\n", sizeof(Struct1));
    
    printf("Struct2布局:\n");
    printf("  int b (4字节) + char a (1字节) + char c (1字节) + 填充 (2字节)\n");
    printf("  总大小:%zu字节\n\n", sizeof(Struct2));
    
    printf("内存对齐原则:\n");
    printf("  1. 成员按其大小对齐\n");
    printf("  2. 结构体大小是最大成员大小的整数倍\n");
    printf("  3. 合理排列成员顺序可节省内存\n");
}

int main() {
    memoryAlignment();
    return 0;
}

优化内存布局

#include <stdio.h>

typedef struct {
    char a;
    char c;
    int b;
} OptimizedStruct;

void optimizeMemoryLayout() {
    printf("=== 东巴文优化内存布局 ===\n\n");
    
    printf("优化前:\n");
    printf("  char a (1) + 填充 (3) + int b (4) + char c (1) + 填充 (3) = 12字节\n\n");
    
    printf("优化后:\n");
    printf("  char a (1) + char c (1) + 填充 (2) + int b (4) = 8字节\n\n");
    
    printf("优化原则:\n");
    printf("  1. 将大小相同的成员放在一起\n");
    printf("  2. 按成员大小降序排列\n");
    printf("  3. 减少填充字节\n");
    printf("  4. 节省内存空间\n");
}

int main() {
    optimizeMemoryLayout();
    return 0;
}

东巴文最佳实践

1. 使用typedef简化类型

#include <stdio.h>
#include <string.h>

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

void useTypedef() {
    printf("=== 东巴文使用typedef简化类型 ===\n\n");
    
    Student student = {"东巴文", 20, 95.5};
    
    printf("typedef优势:\n");
    printf("  1. 简化类型声明\n");
    printf("  2. 提高可读性\n");
    printf("  3. 便于移植\n");
    printf("  4. 隐藏实现细节\n");
    
    printf("\n学生:%s, %d岁, 成绩%.1f\n", student.name, student.age, student.score);
}

int main() {
    useTypedef();
    return 0;
}

2. 合理设计结构体

#include <stdio.h>
#include <string.h>

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

void designStruct() {
    printf("=== 东巴文合理设计结构体 ===\n\n");
    
    printf("设计原则:\n");
    printf("  1. 相关数据组织在一起\n");
    printf("  2. 成员命名清晰明确\n");
    printf("  3. 避免过度嵌套\n");
    printf("  4. 考虑内存对齐\n");
    printf("  5. 提供初始化函数\n");
    printf("  6. 提供操作函数\n");
}

int main() {
    designStruct();
    return 0;
}

3. 使用const保护数据

#include <stdio.h>
#include <string.h>

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

void printStudent(const Student *stu) {
    printf("学生信息:\n");
    printf("  姓名:%s\n", stu->name);
    printf("  年龄:%d\n", stu->age);
    printf("  成绩:%.1f\n", stu->score);
    
    // ❌ 错误:不能修改const指针指向的数据
    // stu->age = 21;
}

void useConst() {
    printf("=== 东巴文使用const保护数据 ===\n\n");
    
    Student student = {"东巴文", 20, 95.5};
    printStudent(&student);
    
    printf("\nconst优势:\n");
    printf("  1. 防止意外修改\n");
    printf("  2. 提高代码安全性\n");
    printf("  3. 明确函数意图\n");
    printf("  4. 便于编译器优化\n");
}

int main() {
    useConst();
    return 0;
}

东巴文验证清单

完成本章学习后,请确认:

  • 理解结构体的定义
  • 掌握结构体的声明
  • 掌握结构体的初始化
  • 掌握结构体成员访问
  • 掌握结构体与函数
  • 掌握结构体数组
  • 掌握结构体指针
  • 掌握结构体的嵌套
  • 理解内存对齐
  • 掌握最佳实践

下一步学习

掌握结构体后,你可以继续学习:

如果遇到问题,欢迎访问 东巴文(db-w.cn) 获取帮助!


东巴文(db-w.cn) - 让编程学习更简单

🎯 东巴文结构体提示:结构体是C语言处理复杂数据的核心工具。在 db-w.cn,我们会通过大量实例帮你掌握结构体!