跳转到内容

C 语言结构体数组

来自代码酷

模板:Note

C语言结构体数组[编辑 | 编辑源代码]

结构体数组是C语言中一种将多个相同类型的结构体变量按顺序存储的数据结构。它结合了数组的批量存储特性和结构体的复合数据类型特性,是处理结构化数据集合的重要工具。

基本概念[编辑 | 编辑源代码]

结构体数组的声明方式与普通数组类似,只是在元素类型处指定为结构体类型。其内存分配遵循以下原则:

  • 所有元素在内存中连续存储
  • 每个元素的大小等于结构体的大小
  • 数组名代表首元素的地址

数学上可以表示为:struct Array[N]={struct0,struct1,...,structN1}

声明与初始化[编辑 | 编辑源代码]

基本声明语法[编辑 | 编辑源代码]

struct 结构体标签 {
    数据类型 成员1;
    数据类型 成员2;
    // ...更多成员
} 数组名[数组长度];

初始化方式[编辑 | 编辑源代码]

结构体数组支持多种初始化方式:

1. 完全初始化(每个成员显式赋值):

struct Point {
    int x;
    int y;
} points[3] = {
    {1, 2},  // 第一个元素
    {3, 4},  // 第二个元素
    {5, 6}   // 第三个元素
};

2. 部分初始化(未指定的成员自动初始化为0):

struct Point points[3] = {
    {1},     // x=1, y=0
    {3, 4}   // x=3, y=4
};           // 第三个元素全为0

3. 指定初始化(C99特性):

struct Point points[3] = {
    [0].x = 1, [0].y = 2,
    [2] = {5, 6}
};

访问结构体数组成员[编辑 | 编辑源代码]

访问结构体数组元素需要结合数组下标和结构体成员访问运算符:

#include <stdio.h>

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

int main() {
    struct Student class[3] = {
        {"Alice", 20, 3.8},
        {"Bob", 21, 3.5},
        {"Charlie", 19, 3.9}
    };
    
    // 访问第二个学生的GPA
    printf("%s's GPA: %.1f\n", class[1].name, class[1].gpa);
    
    // 修改第三个学生的年龄
    class[2].age = 20;
    
    return 0;
}

输出结果:

Bob's GPA: 3.5

内存布局可视化[编辑 | 编辑源代码]

graph LR A[结构体数组] --> B[元素0] A --> C[元素1] A --> D[...] A --> E[元素N-1] B --> F[成员1] B --> G[成员2] B --> H[...] B --> I[成员M] C --> J[成员1] C --> K[成员2] C --> L[...] C --> M[成员M]

高级应用[编辑 | 编辑源代码]

结构体数组作为函数参数[编辑 | 编辑源代码]

结构体数组可以作为函数参数传递,通常需要同时传递数组长度:

void printStudents(struct Student arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("Student %d: %s, %d years, GPA %.1f\n",
               i+1, arr[i].name, arr[i].age, arr[i].gpa);
    }
}

int main() {
    struct Student class[3] = {...}; // 同上例
    printStudents(class, 3);
    return 0;
}

动态分配结构体数组[编辑 | 编辑源代码]

使用malloc动态创建结构体数组:

#include <stdlib.h>

int main() {
    int n = 5;
    struct Student *students = (struct Student*)malloc(n * sizeof(struct Student));
    
    if (students == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    // 使用数组...
    students[0].age = 20;
    
    free(students); // 释放内存
    return 0;
}

实际应用案例[编辑 | 编辑源代码]

学生成绩管理系统是结构体数组的典型应用:

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

#define MAX_STUDENTS 100

struct Student {
    int id;
    char name[50];
    float scores[5]; // 5门课程成绩
    float average;
};

void calculateAverage(struct Student *s) {
    float sum = 0;
    for (int i = 0; i < 5; i++) {
        sum += s->scores[i];
    }
    s->average = sum / 5;
}

int main() {
    struct Student gradebook[MAX_STUDENTS];
    int count = 0;
    
    // 添加学生数据
    gradebook[count].id = 1001;
    strcpy(gradebook[count].name, "张三");
    float tempScores[] = {85.5, 90.0, 78.5, 92.0, 88.5};
    memcpy(gradebook[count].scores, tempScores, sizeof(tempScores));
    calculateAverage(&gradebook[count]);
    count++;
    
    // 显示结果
    printf("ID: %d\nName: %s\nAverage: %.2f\n",
           gradebook[0].id, gradebook[0].name, gradebook[0].average);
    
    return 0;
}

输出结果:

ID: 1001
Name: 张三
Average: 86.90

常见问题与最佳实践[编辑 | 编辑源代码]

问题类型 描述 解决方案
内存对齐 结构体填充可能导致数组大小计算错误 使用sizeof运算符而非手动计算
数组越界 访问超出数组范围的元素 始终检查数组索引有效性
深拷贝问题 直接赋值会进行浅拷贝 对于包含指针的结构体,需要实现深拷贝函数
初始化遗漏 部分成员未初始化导致未定义行为 使用{0}初始化或memset清零

性能考量[编辑 | 编辑源代码]

  • 缓存友好性:结构体数组的连续内存布局对CPU缓存友好
  • 访问模式优化:如果频繁访问特定成员,考虑结构体数组(Array of Structures, AoS)或数组结构体(Structure of Arrays, SoA)的转换
  • 内存占用:大型结构体数组可能消耗大量内存,需考虑动态分配或分块处理

进阶练习[编辑 | 编辑源代码]

1. 编写一个函数,对结构体数组按指定成员进行排序 2. 实现一个动态增长的结构体数组(类似C++的vector) 3. 设计一个包含嵌套结构体的结构体数组系统

模板:Tip