“静态数组的动态数组”

时间:2012-11-28 03:23:55

标签: c types struct static-array

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

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

这应该包含一个动态的顶点列表,每个顶点有3个双打,还有一个动态的面部列表,每个都有3个整数。

2 个答案:

答案 0 :(得分:3)

语法是,C语言的声明方法并不是最干净的C ++继承的...

double (*vertices)[3];

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

过了一段时间,你最终习惯于在表达式上使用倒置的括号方式......

答案 1 :(得分:0)

对于包含两个每个维度为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()的调用中指定顶点数和面数。