结构体

内容简介

结构体用于把多个相关数据组合成一个自定义类型。C 中结构体主要保存数据,常搭配普通函数组织模块;C++ 中 struct 常用于简单数据对象,也可以拥有成员函数。

本篇讲主线用法。C 语言里的结构体布局和 C/C++ 差异见 C语言结构体,联合体 unionC语言联合体,位域见 C语言位域

用法

C++ 结构体

struct Point {
    int x = 0;
    int y = 0;
 
    void move(int dx, int dy)
    {
        x += dx;
        y += dy;
    }
};

C 风格结构体

#include <stdio.h>
 
struct Student {
    char name[32];
    int age;
    double score;
};
 
int main(void)
{
    struct Student stu = {"Alice", 18, 95.5};
    printf("%s %d %.1f\n", stu.name, stu.age, stu.score);
    return 0;
}

typedef 简化写法

typedef struct Student {
    char name[32];
    int age;
} Student;
 
Student stu = {"Bob", 20};

指针访问结构体

void print_student(const Student *student)
{
    if (student == NULL) {
        return;
    }
 
    printf("%s %d\n", student->name, student->age);
}

student->age 等价于 (*student).age

指定初始化

Student stu = {
    .name = "Carol",
    .age = 21
};

指定初始化适合成员较多的结构体,比依赖成员顺序更清楚。

最佳代码实践

  • 把强相关的数据放进结构体,例如学生的姓名、年龄、成绩。
  • 成员命名要清晰,不要使用无意义缩写。
  • C 中常用“结构体 + 操作函数”组织模块,例如 student_initstudent_print
  • C++ 中如果结构体开始承担复杂行为和不变量,考虑改成 class 并控制访问权限。
  • 传递大结构体时,C 使用 const Student *,C++ 优先使用 const Student&
void print_student(const Student& student);

错误用法

struct Student {
    char *name;
};
 
struct Student stu;
strcpy(stu.name, "Alice");  // 错误:name 没有指向有效内存
struct Student stu;
printf("%d\n", stu.age);  // 错误:stu 未初始化,age 值不确定
fwrite(&stu, sizeof(stu), 1, fp);  // 错误倾向:直接写结构体内存不可移植

注意事项

  • 结构体可能存在内存对齐,sizeof(struct) 不一定等于所有成员大小之和。
  • 结构体整体赋值是浅层复制;如果成员里有指针,复制的是地址。
  • 联合体 union 的多个成员共享同一块内存,位域可以按位宽声明成员;细节见 C语言联合体C语言位域
  • C++ 的 structclass 主要默认访问权限不同:struct 默认 publicclass 默认 private

学习路径