我很困惑如何有效地管理(填充和访问)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
。我不知道这是否正常,因此是健壮的。
答案 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;
}
这有点麻烦,因为所有实际数据(foo
和num
)必须传递给创建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}}已不再使用,可以释放。有一些通用的解决方案,如引用计数,或者可能有一些特定于您的应用程序,使问题的答案很容易。