Skip to content

结构体

概述

结构体(Structure)是C语言中一种用户自定义的数据类型,它允许将不同类型的数据组合在一起,形成一个有机的整体。

结构体的定义

基本语法

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

定义结构体变量

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

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

int main() {
    struct Student stu1;
    struct Student stu2;
    
    strcpy(stu1.name, "张三");
    stu1.age = 20;
    stu1.score = 85.5;
    
    printf("姓名: %s\n", stu1.name);
    printf("年龄: %d\n", stu1.age);
    printf("成绩: %.1f\n", stu1.score);
    
    return 0;
}

定义时同时声明变量

c
struct Point {
    int x;
    int y;
} p1, p2;

struct Point p3;

匿名结构体

c
struct {
    int x;
    int y;
} point;

结构体初始化

顺序初始化

c
struct Student stu = {"李四", 22, 90.0};

指定成员初始化(C99)

c
struct Student stu = {
    .name = "王五",
    .age = 21,
    .score = 88.5
};

部分初始化

c
struct Student stu = {.name = "赵六"};

访问结构体成员

点运算符

c
struct Student stu;
stu.age = 20;
stu.score = 85.5;

箭头运算符(指针)

c
struct Student *ptr = &stu;
ptr->age = 21;
ptr->score = 90.0;

// 等价于
(*ptr).age = 21;

结构体数组

c
#include <stdio.h>

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

int main() {
    struct Student students[3] = {
        {"张三", 20, 85.5},
        {"李四", 21, 90.0},
        {"王五", 22, 78.5}
    };
    
    for (int i = 0; i < 3; i++) {
        printf("%s: 年龄=%d, 成绩=%.1f\n", 
               students[i].name, 
               students[i].age, 
               students[i].score);
    }
    
    return 0;
}

结构体指针

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

struct Person {
    char name[50];
    int age;
};

int main() {
    struct Person *ptr;
    
    ptr = (struct Person*)malloc(sizeof(struct Person));
    
    strcpy(ptr->name, "张三");
    ptr->age = 25;
    
    printf("姓名: %s\n", ptr->name);
    printf("年龄: %d\n", ptr->age);
    
    free(ptr);
    
    return 0;
}

结构体作为函数参数

值传递

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

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

void printStudent(struct Student s) {
    printf("姓名: %s, 年龄: %d\n", s.name, s.age);
}

int main() {
    struct Student stu;
    strcpy(stu.name, "张三");
    stu.age = 20;
    
    printStudent(stu);
    
    return 0;
}

指针传递

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

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

void updateAge(struct Student *s, int newAge) {
    s->age = newAge;
}

void printStudent(const struct Student *s) {
    printf("姓名: %s, 年龄: %d\n", s->name, s->age);
}

int main() {
    struct Student stu;
    strcpy(stu.name, "张三");
    stu.age = 20;
    
    printStudent(&stu);
    updateAge(&stu, 25);
    printStudent(&stu);
    
    return 0;
}

嵌套结构体

c
#include <stdio.h>

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

struct Employee {
    char name[50];
    struct Date birthday;
    struct Date hireDate;
};

int main() {
    struct Employee emp = {
        .name = "张三",
        .birthday = {1990, 5, 15},
        .hireDate = {2020, 3, 1}
    };
    
    printf("员工: %s\n", emp.name);
    printf("生日: %d-%d-%d\n", emp.birthday.year, emp.birthday.month, emp.birthday.day);
    printf("入职: %d-%d-%d\n", emp.hireDate.year, emp.hireDate.month, emp.hireDate.day);
    
    return 0;
}

结构体大小与内存对齐

sizeof运算符

c
#include <stdio.h>

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

int main() {
    printf("struct Example 大小: %zu\n", sizeof(struct Example));
    
    return 0;
}

内存对齐规则

c
#include <stdio.h>

struct A {
    char a;
    int b;
    char c;
};

struct B {
    int b;
    char a;
    char c;
};

int main() {
    printf("struct A 大小: %zu\n", sizeof(struct A));  // 12
    printf("struct B 大小: %zu\n", sizeof(struct B));  // 8
    
    return 0;
}

使用#pragma pack修改对齐

c
#include <stdio.h>

#pragma pack(1)
struct Packed {
    char a;
    int b;
    char c;
};
#pragma pack()

int main() {
    printf("struct Packed 大小: %zu\n", sizeof(struct Packed));  // 6
    
    return 0;
}

位域

c
#include <stdio.h>

struct Flags {
    unsigned int isReadable : 1;
    unsigned int isWritable : 1;
    unsigned int isExecutable : 1;
    unsigned int reserved : 5;
};

int main() {
    struct Flags flags = {1, 1, 0, 0};
    
    printf("可读: %d\n", flags.isReadable);
    printf("可写: %d\n", flags.isWritable);
    printf("可执行: %d\n", flags.isExecutable);
    printf("结构体大小: %zu\n", sizeof(flags));
    
    return 0;
}

typedef与结构体

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

typedef struct {
    char name[50];
    int age;
} Person;

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

int main() {
    Person p;
    strcpy(p.name, "张三");
    p.age = 25;
    
    printf("姓名: %s, 年龄: %d\n", p.name, p.age);
    
    Node n1 = {10, NULL};
    Node n2 = {20, NULL};
    n1.next = &n2;
    
    printf("n1.data = %d\n", n1.data);
    printf("n1.next->data = %d\n", n1.next->data);
    
    return 0;
}

结构体与链表

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

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

Node* createNode(int data) {
    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

void appendNode(Node **head, int data) {
    Node *newNode = createNode(data);
    
    if (*head == NULL) {
        *head = newNode;
        return;
    }
    
    Node *current = *head;
    while (current->next != NULL) {
        current = current->next;
    }
    current->next = newNode;
}

void printList(Node *head) {
    Node *current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

void freeList(Node *head) {
    Node *current = head;
    while (current != NULL) {
        Node *temp = current;
        current = current->next;
        free(temp);
    }
}

int main() {
    Node *head = NULL;
    
    appendNode(&head, 10);
    appendNode(&head, 20);
    appendNode(&head, 30);
    
    printList(head);
    
    freeList(head);
    
    return 0;
}

联合体

联合体允许在同一内存位置存储不同类型的数据。

c
#include <stdio.h>

union Data {
    int i;
    float f;
    char str[20];
};

int main() {
    union Data data;
    
    data.i = 10;
    printf("data.i: %d\n", data.i);
    
    data.f = 3.14;
    printf("data.f: %f\n", data.f);
    printf("data.i: %d (已被覆盖)\n", data.i);
    
    return 0;
}

枚举

c
#include <stdio.h>

enum Weekday {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
};

enum Color {
    RED = 1,
    GREEN = 2,
    BLUE = 3
};

int main() {
    enum Weekday today = WEDNESDAY;
    
    if (today == WEDNESDAY) {
        printf("今天是星期三\n");
    }
    
    for (enum Weekday day = SUNDAY; day <= SATURDAY; day++) {
        printf("day = %d\n", day);
    }
    
    enum Color favorite = GREEN;
    printf("最喜欢的颜色编号: %d\n", favorite);
    
    return 0;
}

实践示例

学生管理系统

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

#define MAX_STUDENTS 100

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

typedef struct {
    Student students[MAX_STUDENTS];
    int count;
} StudentManager;

void initManager(StudentManager *manager) {
    manager->count = 0;
}

void addStudent(StudentManager *manager, int id, const char *name, int age, float score) {
    if (manager->count >= MAX_STUDENTS) {
        printf("学生数量已达上限\n");
        return;
    }
    
    Student *s = &manager->students[manager->count];
    s->id = id;
    strcpy(s->name, name);
    s->age = age;
    s->score = score;
    manager->count++;
    
    printf("添加学生成功: %s\n", name);
}

void displayStudents(const StudentManager *manager) {
    printf("\n=== 学生列表 ===\n");
    printf("ID\t姓名\t年龄\t成绩\n");
    printf("--------------------------------\n");
    
    for (int i = 0; i < manager->count; i++) {
        const Student *s = &manager->students[i];
        printf("%d\t%s\t%d\t%.1f\n", s->id, s->name, s->age, s->score);
    }
}

Student* findStudent(StudentManager *manager, int id) {
    for (int i = 0; i < manager->count; i++) {
        if (manager->students[i].id == id) {
            return &manager->students[i];
        }
    }
    return NULL;
}

void updateScore(StudentManager *manager, int id, float newScore) {
    Student *s = findStudent(manager, id);
    if (s != NULL) {
        s->score = newScore;
        printf("更新成功: %s 的新成绩为 %.1f\n", s->name, newScore);
    } else {
        printf("未找到ID为 %d 的学生\n", id);
    }
}

int main() {
    StudentManager manager;
    initManager(&manager);
    
    addStudent(&manager, 1, "张三", 20, 85.5);
    addStudent(&manager, 2, "李四", 21, 90.0);
    addStudent(&manager, 3, "王五", 19, 78.5);
    
    displayStudents(&manager);
    
    updateScore(&manager, 2, 95.0);
    
    displayStudents(&manager);
    
    return 0;
}

小结

结构体是C语言中组织复杂数据的重要工具:

特性说明
定义使用 struct 关键字定义
成员访问使用 .-> 运算符
内存对齐编译器会进行内存对齐优化
位域节省内存空间
typedef简化结构体类型名称

导航