【问题标题】:"dynamic array of static arrays"“静态数组的动态数组”
【发布时间】:2012-11-15 20:14:04
【问题描述】:

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

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

这应该包含一个动态的顶点列表,每个顶点都是 3 个双精度数,以及一个动态的面列表,每个顶点都是 3 个整数。

【问题讨论】:

  • 使用 C++(已标记):std::vector<std::array<double, 3>> vertices;

标签: c types struct static-array


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    double (*vertices)[3];
    

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

    一段时间后,您最终会习惯于表达式中括号的倒置方式...

    【讨论】:

    • 使用double(**verticies)[3] 可能会更好,这样扩展外部数组就意味着复制指针而不是复制数组。如果内部数组的维度可能大于三,则更是如此。当然,这会让 access 语法变得非常可怕。
    • @dmckee:答案解决了问题中的问题。关于副本(如果外部数组确实需要增长),复制指针与 3 int 或 3 double 的成本并没有那么很多,仍然可以使用 @ 987654329@。除非分析确定这是程序中的高成本,否则我不会使已经复杂的代码复杂化。否则我会建议创建一个包含顶点/面的结构,然后有一个动态数组......因为这将简化代码(假设问题中的两个数组具有相同的大小)
    猜你喜欢
    • 1970-01-01
    • 2014-07-21
    • 2011-02-09
    • 2014-06-03
    • 2023-02-10
    • 2012-05-09
    • 2018-09-03
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多