如何在 C 中的结构中包含动态数组?
Posted
技术标签:
【中文标题】如何在 C 中的结构中包含动态数组?【英文标题】:How to include a dynamic array INSIDE a struct in C? 【发布时间】:2011-01-04 21:09:35 【问题描述】:我环顾四周,但无法找到解决这个问题的方法。 这是我的代码:
#include <stdlib.h>
struct my_struct
int n;
char s[]
;
int main()
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
这是 gcc 给我的错误: 错误:灵活数组成员的使用无效
如果我在结构中声明 s 的声明为
,我可以编译它char* s
这可能是一个更好的实现(指针算法比数组快,是吗?) 但我认为在 c 中声明了
char s[]
与
相同char* s
【问题讨论】:
char s[]
与 char *s
相同,只是在函数的参数列表中。
【参考方案1】:
您现在编写它的方式,过去被称为“struct hack”,直到 C99 将其称为“灵活数组成员”。您收到错误(可能无论如何)的原因是它需要跟一个分号:
#include <stdlib.h>
struct my_struct
int n;
char s[];
;
当你为此分配空间时,你想要分配结构体的大小加上你想要的数组空间量:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
在这种情况下,灵活数组成员是一个 char 数组,并且 sizeof(char)==1,因此您不需要乘以它的大小,但就像任何其他 malloc 一样,如果它是一个其他类型的数组:
struct dyn_array
int size;
int data[];
;
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
编辑:这与将成员更改为指针给出了不同的结果。在这种情况下,您(通常)需要两个单独的分配,一个用于结构本身,一个用于指针指向的“额外”数据。使用灵活的数组成员,您可以在单个块中分配所有数据。
【讨论】:
C99 实际上允许这样做 - 呃! 哇,我从来没有见过这个......这是否依赖于“灵活数组成员”作为结构中声明的最后一个字段?您是否被限制为每个结构只有一个“灵活数组成员”? @vicatcu:是的,你的两个问题。如果有记忆,如果你嵌入了一个包含灵活数组成员的结构,它必须是外部结构中的最后一个成员,所以当它们全部放在一起时,灵活数组成员总是最后一项。【参考方案2】:你需要先决定你要做什么。
如果你想要一个结构体,里面有一个指向[独立]数组的指针,你必须将它声明为
struct my_struct
int n;
char *s;
;
在这种情况下,您可以以任何您喜欢的方式创建实际的结构对象(例如自动变量)
struct my_struct ms;
然后为数组独立分配内存
ms.s = malloc(50 * sizeof *ms.s);
其实一般不需要动态分配数组内存
struct my_struct ms;
char s[50];
ms.s = s;
这完全取决于您需要从这些对象中获得什么样的生命周期。如果您的结构是自动的,那么在大多数情况下,数组也是自动的。如果结构对象拥有数组内存,那么这样做根本没有意义。如果结构本身是动态的,那么数组通常也应该是动态的。
请注意,在这种情况下,您有两个独立的内存块:结构和数组。
一种完全不同的方法是使用“struct hack”习语。在这种情况下,数组成为结构的一个组成部分。两者都驻留在单个内存块中。在 C99 中,该结构将被声明为
struct my_struct
int n;
char s[];
;
要创建一个对象,您必须动态分配整个对象
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
在这种情况下,计算内存块的大小以容纳结构成员和运行时大小的尾随数组。
请注意,在这种情况下,您无法创建静态或自动对象等结构对象。最后具有灵活数组成员的结构只能在 C 中动态分配。
您关于指针算法比数组更快的假设是绝对不正确的。根据定义,数组通过指针算术工作,因此它们基本相同。此外,真正的数组(不衰减为指针)通常比指针对象快一点。指针值必须从内存中读取,而数组在内存中的位置是从数组对象本身“已知”(或“计算”)的。
【讨论】:
UV forsizeof *ms + 50 * sizeof *ms->s
:更易于查看和维护。【参考方案3】:
只允许在结构的末尾使用未指定大小的数组,并且仅在某些编译器中有效。它是一个非标准的编译器扩展。 (虽然我想我记得 C++0x 会允许这样做。)
虽然数组不会是从结构中单独分配的。所以你需要分配所有的my_struct
,而不仅仅是数组部分。
我所做的只是给数组一个小但非零的大小。通常 4 个用于字符数组,2 个用于 wchar_t
数组以保持 32 位对齐。
然后,您可以在进行分配时将声明的数组大小考虑在内。我通常不认为斜率小于堆管理器在任何情况下工作的粒度。
另外,我认为您不应该在分配中使用 sizeof(char*)。
这就是我会做的。
struct my_struct
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
;
int main()
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
【讨论】:
【参考方案4】:数组将解析为指针,在这里您必须将s
定义为char *s
。该结构基本上是一个容器,并且必须(IIRC)是固定大小的,因此根本不可能在其中拥有一个动态大小的数组。反正你是malloc
内存,这对你追求的东西没有任何影响。
基本上你是说,s
将指示一个内存位置。请注意,您以后仍然可以使用 s[0]
之类的符号来访问它。
【讨论】:
【参考方案5】:指针运算比数组快,是吗?
根本不是——它们实际上是一样的。数组在编译时转换为指针算法。
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
【讨论】:
【参考方案6】:如果你选择用它声明一个自动变量,我怀疑编译器不知道它需要为 s[] 分配多少空间。
我同意 Ben 所说的,声明你的结构
struct my_struct
int n;
char s[1];
;
另外,为了澄清他关于存储的评论,声明char *s
不会将结构放入堆栈(因为它是动态分配的)并在堆中分配s
,它会解释第一个@将数组的 987654324@ 字节作为指针,因此您不会对您认为的数据进行操作,并且可能会是致命的。
重要的是要记住,尽管指针和数组的操作可能以相同的方式实现,但它们并不是一回事。
【讨论】:
【参考方案7】:将数组存储在c结构中的工作代码,以及如何在数组元素中存储值如果您有任何疑问,请发表评论,我会尽力澄清
结构定义:
struct process
int process_id;
int tau;
double alpha;
int* process_time;
;
进程结构的内存分配:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
循环遍历多个进程并为每个进程更新 process_time 动态数组
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process)
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
从文件中逐行读取数据,存储到 process_time 数组中,然后从存储的值中打印出来,下一个 while 循环在进程 while 循环内
while(tick_count < number_of_ticks)
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
tick_count = 0;
【讨论】:
【参考方案8】:生成的代码将是相同的(数组和 ptr)。除了数组无法编译这一事实之外,
顺便说一句 - 使用 c++ 并使用向量
【讨论】:
建议我使用 c++ 和向量绝不是建设性的建议。你可以直接说:聘请软件工程师为你编写程序 生成的代码甚至不会完全一样。数组不是指针。将数组嵌入到结构中或从结构中指向数组是完全不同的两件事。 是的,你是对的,它们并不相同。我想说的是,如果代码正在处理作为 foo * 或 foo [] 传递给它的东西,那么代码将是相同的。本质上没有性能差异 Tom,有些人不知道 STL、c++ vector 等。我试图发布一些开箱即用的东西。如果你觉得这没有帮助,我很抱歉。以上是关于如何在 C 中的结构中包含动态数组?的主要内容,如果未能解决你的问题,请参考以下文章
C - 当我尝试将结构从数组复制到结构中包含的数组时出现问题