C - "dynamic array of static arrays"



如何在C中指定静态数组的动态数组
我想制作一个包含两个静态数组的动态数组的结构。

struct indexed_face_set {
double * [3] vertices;
int * [3] faces;
};

这应该包含一个顶点的动态列表,每个顶点是3个双顶点,以及一个面的动态列表(每个面是3个int)。

语法是,C的声明方法不是最干净的,C++继承了。。。

double (*vertices)[3];

该声明意味着vertices是指向double [3]对象的指针。请注意,括号是必需的,否则(如在double *vertices[3]中)它将意味着3个double*的数组。

一段时间后,你终于习惯了表达式中括号的倒置方式。。。

对于一个结构包含两个维度为3的数组的特定情况,将数组作为结构的一部分会更简单,而不是单独动态分配它们:

struct indexed_face_set
{
double vertices[3];
int    faces[3];
};

然而,在某些情况下,处理动态数组分配是有意义的。在这种情况下,您需要一个指向结构中数组的指针(而不是指针数组)。所以,你需要写:

struct indexed_face_set
{
double (*vertices)[3];
int    (*faces)[3];
};

要分配一个完整的struct indexed_face_set,你需要使用类似new_indexed_face_set()的东西,而要释放一个,你需要用类似destroy_indexed_face_set():的东西

struct indexed_face_set *new_indexed_face_set(void)
{
struct indexed_face_set *new_ifs = malloc(sizeof(*new_ifs));
if (new_ifs != 0)
{
double (*v)[3] = malloc(sizeof(*v));
int    (*f)[3] = malloc(sizeof(*f));
if (v == 0 || f == 0)
{
free(v);
free(f);
free(new_ifs);
new_ifs = 0;
}
else
{
new_ifs->vertices = v;
new_ifs->faces = f;
}
}
return(new_ifs);
}
void destroy_indexed_face_set(struct indexed_face_set *ifs)
{
if (ifs != 0)
{
free(ifs->vertices);
free(ifs->faces);
free(ifs);
}
}

然后你可以这样使用它:

void play_with_ifs(void)
{
struct indexed_face_set *ifs = new_indexed_face_set();
if (ifs != 0)
{
(*ifs->vertices)[0] = 3.14159;
(*ifs->vertices)[1] = 2.71813;
(*ifs->vertices)[2] = 1.61803;
(*ifs->faces)[0] = 31;
(*ifs->faces)[1] = 30;
(*ifs->faces)[2] = 29;
do_something_fancy(ifs);
destroy_indexed_face_set(ifs);
}
}

请注意,使用指向数组的指针的表示法是适度混乱的;人们不经常使用它们的一个原因。

您可以使用这个片段作为标头的主体:

#ifndef DASS_H_INCLUDED
#define DASS_H_INCLUDED
struct indexed_face_set;
extern void play_with_ifs(void);
extern void do_something_fancy(struct indexed_face_set *ifs);
extern void destroy_indexed_face_set(struct indexed_face_set *ifs);
extern struct indexed_face_set *new_indexed_face_set(void);
#endif /* DASS_H_INCLUDED */

它不需要包含任何额外的标题;它不需要这些函数的结构定义的细节。你应该用合适的收割台护罩把它包起来。


因为上面的代码在使用数组时有点混乱,所以大多数人会使用更简单的表示法。上面的标题可以保持不变,但代码可以更改为:

struct indexed_face_set
{
double *vertices;
int    *faces;
};
struct indexed_face_set *new_indexed_face_set(void)
{
struct indexed_face_set *new_ifs = malloc(sizeof(*new_ifs));
if (new_ifs != 0)
{
double *v = malloc(3 * sizeof(*v));
int    *f = malloc(3 * sizeof(*f));
if (v == 0 || f == 0)
{
free(v);
free(f);
free(new_ifs);
new_ifs = 0;
}
else
{
new_ifs->vertices = v;
new_ifs->faces = f;
}
}
return(new_ifs);
}
void destroy_indexed_face_set(struct indexed_face_set *ifs)
{
if (ifs != 0)
{
free(ifs->vertices);
free(ifs->faces);
free(ifs);
}
}
void play_with_ifs(void)
{
struct indexed_face_set *ifs = new_indexed_face_set();
if (ifs != 0)
{
ifs->vertices[0] = 3.14159;
ifs->vertices[1] = 2.71813;
ifs->vertices[2] = 1.61803;
ifs->faces[0] = 31;
ifs->faces[1] = 30;
ifs->faces[2] = 29;
do_something_fancy(ifs);
destroy_indexed_face_set(ifs);
}
}

这更容易理解和使用,通常被认为是更惯用的C.

由于每个数组的大小是固定的,因此没有特别需要在结构中记录大小。如果大小在运行时发生变化,特别是如果一些索引面集有8个顶点和6个面(长方体?),那么您可能需要记录结构中数组的大小。您还可以在对new_indexed_face_set()的调用中指定顶点数和面数。

最新更新