如何构建和管理这个复杂的C数据结构?

时间:2011-10-26 10:05:49

标签: c data-structures struct

我很困惑如何有效地管理(填充和访问)C中的以下数据结构。为了简要描述,我有一个包含另一个结构的成员的结构,并且该结构具有另一个不同的成员结构等等。像这样:

typedef struct
{
    int num;
} D;

typedef struct
{
    D *boo;
} C;

typedef struct
{
    C *far;
} B;

typedef struct
{
    int foo;
    B *bar;
} A;

A *func() {
    A *var;
    // POPULATE var
}

int main(...) {
    A *a = func();
    // PRINTING
}

那么,哪种方式是管理这种数据结构的最佳方式?我的意思是如何填充这个A型指针的数据?

想象一下,我即将打印a保留的所有数据(// PRINTING),我想我会得到类似的内容:a->bar->far->boo->num。我不知道这是否正常,因此是健壮的。

2 个答案:

答案 0 :(得分:3)

例如,这不会更容易Python,如果你选择这样一个分散的设计,那么管理它会有点痛苦。

打印就像你说的那样,C ->运算符通常就是这样使用的。当然,如果可能存在结构不完整的NULL指针,则需要在取消引用指针之前检查它,否则您将有未定义的行为。

最好通过编写函数在每一层创建一个实例来完成填充,然后可以在链中相互调用以设置最顶层的类型:

D* d_create(int num);
C* c_create(int num);
B* b_create(int num);

A* a_create(int foo, int num)
{
   A* a = malloc(sizeof *a);
   if(a != NULL)
   {
     a->foo = foo;
     a->bar = b_create(num);
     if(a->bar != NULL)
       return a;
     free(a);
   }
   return NULL;
}

这有点麻烦,因为所有实际数据(foonum)必须传递给创建A实例的顶级函数,但它有效而且非常直截了当。

注意我们如何通过确保B指针不是NULL来捕获来自较低级别内存分配器的错误。其他create - 函数也需要进行这类检查。

答案 1 :(得分:0)

如果不知道为什么选择使用指针,就无法回答“我该如何管理”。如果每个A拥有自己的B等等,那么您需要在分配B时分配A,并在释放{{1}时将其释放}}。但在这种情况下,指针是无用的,并创建额外的工作。你可以做到:

A

如果指针的原因是您可能有多个typedef struct { int num; } D; typedef struct { D boo; } C; typedef struct { C far; } B; typedef struct { int foo; B bar; } A; A func() { // don't necessarily need to return a pointer here either A var; var.foo = 1; var.bar.far.boo.num = 2; return var; } 实例都指向同一个A实例,那么您需要决定如何知道该B的实例{1}}已不再使用,可以释放。有一些通用的解决方案,如引用计数,或者可能有一些特定于您的应用程序,使问题的答案很容易。