C语言 如何在 C 中的结构中包含动态数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2060974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to include a dynamic array INSIDE a struct in C?
提问by Tom
I have looked around but have been unable to find a solution to what must be a well asked question. Here is the code I have:
我环顾四周,但一直无法找到必须是一个很好问的问题的解决方案。这是我的代码:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me: error: invalid use of flexible array member
这是gcc给我的错误:错误:灵活数组成员的无效使用
I can get it to compile if i declare the declaration of s inside the struct to be
如果我将结构中的 s 声明声明为
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?) but I thought in c a declaration of
这可能是一个更好的实现(指针算术比数组快,是吗?)但我认为在 ca 声明中
char s[]
is the same as
是相同的
char* s
回答by Jerry Coffin
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
你现在编写它的方式,曾经被称为“结构黑客”,直到 C99 将它祝福为“灵活数组成员”。您收到错误的原因(可能无论如何)是它后面需要跟一个分号:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plusthe amount of space you want for the array:
当您为此分配空间时,您希望分配结构的大小加上数组所需的空间量:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
在这种情况下,灵活数组成员是一个 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));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
编辑:这与将成员更改为指针的结果不同。在这种情况下,您(通常)需要两个单独的分配,一个用于结构本身,另一个用于指针指向的“额外”数据。使用灵活的数组成员,您可以在单个块中分配所有数据。
回答by AnT
You need to decide what it is you are trying to do first.
您需要先决定要尝试做什么。
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
如果你想要一个结构体,里面有一个指向 [independent] 数组的指针,你必须将它声明为
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
在这种情况下,您可以按照您喜欢的任何方式创建实际的结构对象(例如自动变量)
struct my_struct ms;
and then allocate the memory for the array independently
然后独立为数组分配内存
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
实际上,一般不需要动态分配数组内存
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object ownsthe array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
这完全取决于您需要从这些对象中获得什么样的生命周期。如果您的结构是自动的,那么在大多数情况下,数组也将是自动的。如果 struct 对象拥有数组内存,那么做其他事情根本没有意义。如果结构本身是动态的,那么数组通常也应该是动态的。
Note that in this case you have two independent memory blocks: the struct and the array.
请注意,在这种情况下,您有两个独立的内存块:结构和数组。
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
一种完全不同的方法是使用“struct hack”习语。在这种情况下,数组成为结构的一个组成部分。两者都驻留在单个内存块中。在 C99 中,结构体将被声明为
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
并创建一个对象,你必须动态分配整个东西
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
在这种情况下,计算内存块的大小以容纳结构成员和运行时大小的尾随数组。
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
请注意,在这种情况下,您无法选择将此类结构对象创建为静态或自动对象。末尾具有灵活数组成员的结构只能在 C 中动态分配。
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
你关于指针算术比数组更快的假设是绝对不正确的。根据定义,数组通过指针算术工作,因此它们基本相同。此外,真正的数组(未衰减为指针)通常比指针对象快一点。指针值必须从内存中读取,而数组在内存中的位置是从数组对象本身“已知”(或“计算”)的。
回答by John Knoeller
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
未指定大小的数组只允许在结构的末尾使用,并且仅适用于某些编译器。它是一个非标准的编译器扩展。(虽然我想我记得 C++0x 会允许这样做。)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
但是,数组不会从结构中单独分配。所以你需要分配所有的my_struct,而不仅仅是数组部分。
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_tarrays to preserve 32 bit alignment.
我所做的只是给数组一个小但非零的大小。通常 4 个用于字符数组,2 个用于wchar_t数组以保持 32 位对齐。
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
然后,您可以在进行分配时考虑数组的声明大小。在任何情况下,我通常不认为 slop 小于堆管理器工作的粒度。
Also, I think you should not be using sizeof(char*) in your allocation.
另外,我认为您不应该在分配中使用 sizeof(char*) 。
This is what I would do.
这就是我要做的。
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]);
}
回答by Duncan
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
我怀疑编译器不知道它需要为 s[] 分配多少空间,如果您选择用它声明一个自动变量。
I concur with what Ben said, declare your struct
我同意 Ben 所说的,声明你的结构
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *swon't put the struct on the stack (since it is dynamically allocated) and allocate sin the heap, what it will do is interpret the first sizeof(char *)bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
此外,为了澄清他对存储的评论,声明char *s不会将结构放在堆栈上(因为它是动态分配的)并s在堆中分配,它将做的是sizeof(char *)将数组的第一个字节解释为指针,所以你不会对您认为的数据进行操作,并且可能是致命的。
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
重要的是要记住,尽管对指针和数组的操作可能以相同的方式实现,但它们并不是一回事。
回答by Mark Elliot
Arrays will resolve to pointers, and here you mustdefine sas char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
数组将解析为指针,在这里您必须定义s为char *s. 该结构基本上是一个容器,并且必须 (IIRC) 是固定大小的,因此在其中包含动态大小的数组是不可能的。由于您malloc无论如何都在使用内存,因此这对您所追求的内容没有任何影响。
Basically you're saying, swill indicate a memory location. Note that you can still access this later using notation like s[0].
基本上你是说,s将指示一个内存位置。请注意,您稍后仍可以使用诸如s[0].
回答by Alexander Gessler
pointer arithmetic is faster than arrays, yes?
指针算术比数组快,是吗?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
完全不是 - 它们实际上是一样的。数组在编译时转换为指针算术。
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
回答by pm100
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
生成的代码将是相同的(数组和 ptr)。除了数组不会编译这一事实之外
and BTW - do it c++ and use vector
和顺便说一句 - 做 c++ 并使用向量

