如何在C中包含动态数组INSIDE结构?

Tom*_*Tom 45 c arrays struct pointers memory-management

我环顾四周,但一直无法找到解决问题的问题.这是我的代码:

 #include <stdlib.h>

struct my_struct {
    int n;
    char s[]
};

int main()
{
    struct my_struct ms;
    ms.s = malloc(sizeof(char*)*50);
}
Run Code Online (Sandbox Code Playgroud)

这里是错误gcc给我的:错误:无效使用灵活的数组成员

如果我在结构中声明s的声明,我可以编译它

char* s
Run Code Online (Sandbox Code Playgroud)

这可能是一个优秀的实现(指针算法比数组快,是吗?)但我想在ca声明中

char s[]
Run Code Online (Sandbox Code Playgroud)

是相同的

char* s
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 71

你现在写它的方式,曾被称为"结构黑客",直到C99祝福它为"灵活的阵列成员".您收到错误(可能无论如何)的原因是它需要后面跟一个分号:

#include <stdlib.h>

struct my_struct {
    int n;
    char s[];
};
Run Code Online (Sandbox Code Playgroud)

为此分配空间时,您希望分配结构的大小加上数组所需的空间量:

struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,灵活的数组成员是一个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));
Run Code Online (Sandbox Code Playgroud)

编辑:这会将成员更改为指针,从而产生不同的结果.在这种情况下,您(通常)需要两个单独的分配,一个用于结构本身,另一个用于指针指向的"额外"数据.使用灵活的阵列成员,您可以在一个块中分配所有数据.

  • 哇,我从来没有见过这个......这是否依赖于"灵活的数组成员"是结构中声明字段的最后一件事?您是否仅限于每个结构只有一个"灵活的数组成员"? (3认同)

AnT*_*AnT 20

你需要先决定你要做的是什么.


如果你想要一个带有指向[独立]数组的指针的结构,你必须将它声明为

struct my_struct { 
  int n; 
  char *s;
}; 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以以任何方式创建实际的struct对象(例如,自动变量)

struct my_struct ms;
Run Code Online (Sandbox Code Playgroud)

然后独立分配数组的内存

ms.s = malloc(50 * sizeof *ms.s);  
Run Code Online (Sandbox Code Playgroud)

实际上,通常不需要动态分配数组内存

struct my_struct ms;
char s[50];

ms.s = s;
Run Code Online (Sandbox Code Playgroud)

这一切都取决于您需要从这些对象中获得什么样的生命周期.如果你的结构是自动的,那么在大多数情况下,数组也是自动的.如果struct对象拥有数组内存,那么完全没有意义.如果结构本身是动态的,那么数组通常也应该是动态的.

请注意,在这种情况下,您有两个独立的内存块:struct和array.


一种完全不同的方法是使用"struct hack"成语.在这种情况下,数组成为结构的组成部分.两者都驻留在单个内存块中.在C99中,结构将声明为

struct my_struct { 
  int n; 
  char s[];
}; 
Run Code Online (Sandbox Code Playgroud)

并创建一个对象,你必须动态分配整个事物

struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,计算内存块的大小以容纳结构成员和运行时大小的尾随数组.

请注意,在这种情况下,您无法选择将此类结构对象创建为静态或自动对象.最后具有灵活数组成员的结构只能在C中动态分配.


关于指针aritmetics的假设比数组更快是绝对错误的.根据定义,数组通过指针算术运算,因此它们基本相同.而且,真正的数组(不衰减到指针)通常比指针对象快一点.必须从内存中读取指针值,而数组在内存中的位置是从数组对象本身"已知"(或"计算")的.