如何在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()
的调用中指定顶点数和面数。