Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中的结构中包含动态数组?_C_Pointers_Arrays_Struct_Memory Management - Fatal编程技术网

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

如何在C中的结构中包含动态数组?,c,pointers,arrays,struct,memory-management,C,Pointers,Arrays,Struct,Memory Management,我环顾四周,但无法找到一个解决方案,这个问题一定是问得很好的。 以下是我的代码: #include <stdlib.h> struct my_struct { int n; char s[] }; int main() { struct my_struct ms; ms.s = malloc(sizeof(char*)*50); } 这可能是一个更好的实现(指针算法比数组快,是吗?) 但我认为c是一个 char s[] 与 char* s

我环顾四周,但无法找到一个解决方案,这个问题一定是问得很好的。 以下是我的代码:

 #include <stdlib.h>

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

int main()
{
    struct my_struct ms;
    ms.s = malloc(sizeof(char*)*50);
}
这可能是一个更好的实现(指针算法比数组快,是吗?) 但我认为c是一个

char s[]

char* s

数组将解析为指针,这里您必须将
s
定义为
char*s
。结构基本上是一个容器,并且必须(IIRC)是固定大小的,因此在其中包含一个动态大小的数组是不可能的。既然你正在
malloc
ing内存,这对你所追求的不会有任何影响

基本上你是说,
s
将指示内存位置。请注意,您以后仍然可以使用类似于
s[0]
的表示法来访问它

指针运算比数组快,是吗

一点也不——它们实际上是一样的。数组在编译时转换为指针算术

char test[100];
test[40] = 12;

// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;

生成的代码将是相同的(阵列和ptr)。除了数组本身不会编译这一事实之外


和btw——使用C++,使用向量

现在你所写的方法,以前称为“结构HACK”,直到C99祝福它成为“灵活数组成员”。出现错误(可能无论如何)的原因是,它后面必须跟一个分号:

#include <stdlib.h>

struct my_struct {
    int n;
    char s[];
};
在本例中,灵活数组成员是一个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));

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

只允许在结构末尾使用未指定大小的数组,并且只能在某些编译器中使用。它是一个非标准的编译器扩展。(尽管我想我记得C++0x将允许这样做。)

不过,阵列将不会是结构中的单独分配。因此,您需要分配所有的
my_struct
,而不仅仅是数组部分

我所做的只是给数组一个小但非零的大小。通常4个用于字符数组,2个用于
wchar\u t
数组以保持32位对齐

然后,在进行分配时,可以考虑声明的数组大小。我通常不认为slop在任何情况下都小于堆管理器工作的粒度

另外,我认为您不应该在分配中使用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]);
}

你需要先决定你想做什么


如果你想有一个内部有指向[independent]数组指针的结构,你必须将它声明为

struct my_struct { 
  int n; 
  char *s;
}; 
在这种情况下,您可以按照自己喜欢的任何方式创建实际的struct对象(例如,自动变量)

然后为阵列独立分配内存

ms.s = malloc(50 * sizeof *ms.s);  
事实上,通常不需要动态分配阵列内存

struct my_struct ms;
char s[50];

ms.s = s;
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
这完全取决于您需要从这些对象获得什么样的生存期。如果结构是自动的,那么在大多数情况下数组也是自动的。如果struct对象拥有数组内存,那么这样做没有任何意义。如果结构本身是动态的,那么数组通常也应该是动态的

请注意,在本例中,您有两个独立的内存块:struct和array


另一种完全不同的方法是使用“struct hack”习惯用法。在这种情况下,数组成为结构不可分割的一部分。两者都驻留在单个内存块中。在C99中,结构将声明为

struct my_struct { 
  int n; 
  char s[];
}; 
要创建一个对象,您必须动态地分配整个对象

struct my_struct ms;
char s[50];

ms.s = s;
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
在这种情况下,计算内存块的大小是为了容纳结构成员和运行时大小的尾部数组

请注意,在这种情况下,您无法选择创建静态或自动对象等结构对象。末尾具有灵活数组成员的结构只能在C中动态分配



你关于指针算术比数组快的假设是绝对错误的。根据定义,数组通过指针算法工作,因此它们基本相同。此外,真正的数组(不衰减为指针)通常比指针对象快一点。指针值必须从内存中读取,而数组在内存中的位置是从数组对象本身“已知”(或“计算”)的。

如果您选择声明一个自动变量,我怀疑编译器不知道需要为s[]分配多少空间

我同意本说的,声明你的结构

struct my_struct {
    int n;
    char s[1];
};
另外,为了澄清他关于存储的评论,声明
char*s
不会将结构放在堆栈上(因为它是动态分配的)并在堆中分配
s
,它将把数组的第一个
sizeof(char*)
字节解释为指针,这样就不会对您认为是的数据进行操作,而且可能会致命


重要的是要记住,尽管指针和数组的操作可以用相同的方式实现,但它们不是同一回事。

建议我使用C++和向量不是一个建设性的建议。你可以说:请一位软件工程师为你编写程序,生成的代码甚至不会完全相同。数组不是指针。将数组嵌入结构或指向结构中的数组是两件完全不同的事情。是的,你是对的,它们不完全相同。我想说的是,如果代码正在处理某个作为foo*或foo[]传递给它的东西
struct my_struct {
    int n;
    char s[1];
};