结构体(struct)是C语言中用于将不同数据类型组合成复合数据类型的自定义机制,通过定义成员变量并使用点操作符(.)访问成员(如struct_var.member)或指针箭头操作符(->)访问结构体指针成员(如struct_ptr->member),广泛应用于组织复杂数据(如学生信息、链表节点、嵌套地址等),是构建高效数据结构和处理现实问题的核心工具。

一、什么是结构体

结构体(struct)是C语言中一种自定义的数据类型,它允许我们将多个不同类型的变量组合在一起,形成一个新的复合数据类型。结构体本质上是一种"容器",可以把相关的信息打包在一起。

为什么需要结构体?

  • 基本数据类型(int、char、float等)无法完整描述现实中的复杂对象
  • 例如:描述一名学生需要姓名(字符串)、年龄(整型)、成绩(浮点型)等不同类型的属性

二、结构体的定义

1. 基本定义语法

// 方法1:先定义结构体类型,再声明变量
struct 结构体名 {
    成员类型 成员1;
    成员类型 成员2;
    ...
};

struct 结构体名 变量名1, 变量名2, ...;

// 方法2:定义结构体类型的同时声明变量
struct 结构体名 {
    成员类型 成员1;
    成员类型 成员2;
    ...
} 变量名1, 变量名2, ...;

// 方法3:匿名结构体(只能使用一次)
struct {
    成员类型 成员1;
    成员类型 成员2;
    ...
} 变量名1, 变量名2, ...;

2. 使用typedef简化

// 使用typedef创建别名
typedef struct {
    成员类型 成员1;
    成员类型 成员2;
    ...
} 结构体别名;

// 现在可以直接使用别名
结构体别名 变量名1, 变量名2, ...;

三、结构体的初始化和使用

1. 结构体变量的初始化

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

int main() {
    // 方法1:声明时初始化
    struct Student stu1 = {"张三", 20, 90.5};
    
    // 方法2:先声明后逐个赋值
    struct Student stu2;
    strcpy(stu2.name, "李四");  // 字符串需要使用strcpy
    stu2.age = 21;
    stu2.score = 85.5;
    
    // 方法3:部分初始化(未初始化的成员默认为0)
    struct Student stu3 = {"王五"};  // age=0, score=0.0
    
    // 方法4:指定成员初始化(C99标准)
    struct Student stu4 = {.name = "赵六", .score = 95.0};
}

2. 访问结构体成员

// 访问结构体成员使用点操作符(.)
stu1.name = "张三";
stu1.age = 20;
stu1.score = 90.5;

// 打印结构体成员
printf("姓名: %s, 年龄: %d, 成绩: %.1f\n", stu1.name, stu1.age, stu1.score);

3. 结构体指针

// 定义结构体指针
struct Student *stu_ptr;
struct Student stu;

// 指针指向结构体变量
stu_ptr = &stu;

// 通过指针访问结构体成员(使用->操作符)
stu_ptr->name = "王五";
stu_ptr->age = 21;
stu_ptr->score = 88.5;

// 也可以用 (*stu_ptr).name 访问,但->更简洁

四、结构体数组

// 定义结构体数组
struct Student students[3];

// 初始化数组元素
strcpy(students[0].name, "张三");
students[0].age = 20;
students[0].score = 90.5;

strcpy(students[1].name, "李四");
students[1].age = 21;
students[1].score = 85.5;

// 通过下标访问
printf("第二个学生: %s, %d岁, %.1f分\n", students[1].name, students[1].age, students[1].score);

五、结构体嵌套

// 定义嵌套结构体
struct Address {
    char street[50];
    char city[30];
    char zip[10];
};

struct Student {
    char name[20];
    int age;
    float score;
    struct Address addr;  // 嵌套结构体
};

// 使用嵌套结构体
struct Student stu;
strcpy(stu.addr.street, "长安街");
strcpy(stu.addr.city, "北京");
strcpy(stu.addr.zip, "100000");

六、结构体的内存对齐

结构体在内存中的存储遵循对齐规则:

  1. 首个成员从偏移量0开始
  2. 后续成员按编译器对齐系数与自身长度较小值对齐
  3. 整体长度还需按最大成员长度对齐

例如,考虑以下结构体:

struct Example {
    char a;      // 1字节
    int b;       // 4字节
    char c;      // 1字节
};

在32位系统中,内存布局可能如下(假设对齐系数为4):

  • a: 0-0
  • b: 4-7(跳过1字节对齐)
  • c: 8-8

结构体总大小为12字节(而非6字节)。

七、结构体的实际应用

结构体常用于构建复杂数据结构,如:

  • 链表(包含指向自身类型的指针)
  • 树结构
  • 数据库记录
  • 网络数据包
// 链表节点结构体
struct Node {
    int data;
    struct Node *next;  // 指向自身类型的指针
};

总结

结构体是C语言中非常重要的数据类型,它允许我们将不同类型的变量组合在一起,形成一个有意义的整体。通过结构体,我们可以更清晰、更高效地组织和处理复杂数据。

结构体的定义、初始化、成员访问和指针使用是C语言编程中的基础技能,掌握这些内容对于编写更复杂的程序至关重要。