亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> C语言

掌握 C 语言结构体柔性数组成员实现动态数据处理

结构体中的柔性数组成员

柔性数组成员用于在结构体中处理不定大小的数组,其大小在运行时确定。结构体是 C 语言中将多个不同数据类型的成员组合在一起的用户自定义数据类型。

声明结构体的语法如下:

 struct StructName { data_type member1; data_type member2; // ... }; 

每个成员可以有不同的数据类型。

柔性数组成员通过在结构体末尾放置一个动态大小的数组,与固定大小的成员共同存储在一块连续内存中,扩展了结构体的功能。本章将介绍其在结构体中的工作原理。

结构体中的柔性数组成员

柔性数组成员是结构体中没有固定大小的数组,其内存通过 malloc()、calloc() 等函数在运行时动态分配,声明时使用空方括号 []。

柔性数组成员必须声明在结构体的末尾,且前面至少要有一个其他成员。

在结构体中声明柔性数组成员的语法:

 struct StructName { data_type member1; data_type flexible_array[]; // 柔性数组成员 }; 

其中,data_type 是数组元素类型,arrayName[] 是无固定大小的柔性数组。

柔性数组成员的内存分配

柔性数组成员无固定大小,编译器不在结构体内为其分配内存。sizeof 运算符计算结构体大小时仅包含固定成员,不包括柔性数组。因此创建此类结构体时需手动分配内存。

所需总内存计算公式:

 总内存 = sizeof(结构体) + (元素数量 × sizeof(元素类型)) 

其中,sizeof(结构体) 给出固定成员占用内存,(元素数量 × sizeof(元素类型)) 给出柔性数组所需内存,两者之和即为总分配内存。

示例 1:为柔性数组成员分配内存

下例定义一个包含一个固定成员和一个柔性数组的结构体,并为柔性数组分配内存。

 #include <stdio.h> #include <stdlib.h> struct Example { int id; int arr[]; // 柔性数组成员 }; int main() { int size = 5; // 分配结构体 + 柔性数组内存 struct Example *e = malloc(sizeof(struct Example) + size * sizeof(int)); if (e != NULL) { printf("Total allocated memory: %zu bytes\n", sizeof(struct Example) + size * sizeof(int)); free(e); } return 0; } 

此处 sizeof(struct Example) 给出 id 成员占用的 4 字节。柔性数组内存:5 × sizeof(int) = 20 字节。总分配内存 4 + 20 = 24 字节。输出:

 Total allocated memory: 24 bytes 

示例 2:访问结构体中的柔性数组

本例定义 Student 结构体,包含固定成员 id 和柔性数组成员 marks。动态分配柔性数组内存并访问其元素。访问超出分配大小的元素会导致未定义行为,故仅访问 marks[0] 至 marks[2]。

 #include <stdio.h> #include <stdlib.h> struct Student { int id; int marks[]; // 柔性数组成员 }; int main() { int subjects = 3; // 分配结构体 + 柔性数组内存 struct Student *s = malloc(sizeof(struct Student) + subjects * sizeof(int)); if (s != NULL) { s->id = 102; s->marks[0] = 80; s->marks[1] = 75; s->marks[2] = 88; printf("Student ID: %d\n", s->id); printf("Marks: %d, %d, %d\n", s->marks[0], s->marks[1], s->marks[2]); printf("Total allocated memory: %zu bytes\n", sizeof(struct Student) + subjects * sizeof(int)); free(s); } return 0; } 

输出:

 Student ID: 102 Marks: 80, 75, 88 Total allocated memory: 16 bytes 

柔性数组成员的动态调整大小

柔性数组可使用 realloc() 函数 调整大小。该函数会扩展现有内存块,或分配新块并自动复制原有数据。

调整柔性数组大小时,按以下公式计算新总内存大小并调用 realloc():

 sizeof(结构体) + (新元素数量 × sizeof(元素类型)) 

注意:务必用临时指针保存 realloc() 的返回值。若分配失败,原指针仍有效。调整后更新大小计数器,并仅初始化新增元素。

示例 3:柔性数组成员的动态调整大小

本例创建 Student 结构体 初始容纳 3 个成绩,随后用 realloc() 扩展至 6 个成绩。原有成绩保持不变,无需手动复制。

 #include <stdio.h> #include <stdlib.h> struct Student { int id; int count; // 用于跟踪当前数组大小 int marks[]; // 柔性数组成员 }; int main() { // 步骤 1:初始分配 3 个成绩 int initial_elements = 3; struct Student *s = malloc(sizeof(struct Student) + initial_elements * sizeof(int)); if (s != NULL) { s->id = 101; s->count = initial_elements; // 记录当前数组大小 // 显示初始大小 printf("Structure size: %zu bytes\n", sizeof(struct Student)); // 输出:8 字节 (id + count) printf("Initial array elements: %d\n", s->count); // 输出:3 printf("Initial total memory: %zu bytes\n", sizeof(struct Student) + initial_elements * sizeof(int)); // 输出:20 字节 // 步骤 2:调整大小至 6 个成绩 int new_elements = 6; struct Student *temp = realloc(s, sizeof(struct Student) + new_elements * sizeof(int)); if (temp != NULL) { s = temp; s->count = new_elements; // 更新数组大小跟踪器 // 显示新大小 printf("\nAfter resizing:\n"); printf("Structure size: %zu bytes\n", sizeof(struct Student)); // 仍为 8 字节 printf("New array elements: %d\n", s->count); // 输出:6 printf("New total memory: %zu bytes\n", sizeof(struct Student) + new_elements * sizeof(int)); // 输出:32 字节 } free(s); } return 0; } 

输出显示结构体大小及初始、调整后的总内存:

 Structure size: 8 bytes Initial array elements: 3 Initial total memory: 20 bytes After resizing: Structure size: 8 bytes New array elements: 6 New total memory: 32 bytes 

本章介绍了 C 语言结构体中的柔性数组成员。它们声明在结构体末尾,处理变长数据,节省内存,轻松适应不同数据规模。同时演示了分配、访问和调整大小的方法。

C语言

  1. C# 教程 PDF 完整版——243+ 页零基础实战案例(立即下载)
  2. C 语言多维数组详解:二维与三维数组实战
  3. 理解C语言运算符优先级与结合性:清晰指南
  4. C# 接口详解:定义、示例与实战应用
  5. 掌握 C# 数组:声明、初始化与核心操作完全指南
  6. Coded UI 测试自动化框架:从入门到实战的完整指南
  7. C# 索引器完全指南:让对象像数组一样访问、重载与多参数索引器
  8. 掌握 C++ switch-case:语法、用法与实战示例
  9. C++命名空间完全指南:解决命名冲突、using指令、嵌套与离散定义
  10. 掌握 C++ break 语句:跳出循环与 switch 的核心控制流
  11. C# 继承完全指南:基类、派生类、初始化与多重继承替代方案
  12. C# 集合大全:栈、队列、列表与哈希表的核心用法