【发布时间】:2019-10-28 18:04:18
【问题描述】:
我知道以前可能有人问过这个问题,但我想采取我的方法并获得意见或可能是更好的方法。
我有三个文件 a.h a.c 和 main.c 关于结构的函数原型将在 a.h 而实现将在 a.c 并从 main.c 调用结构将很简单,它看起来像这个
struct ctx{
int x;
};
我希望a.c 能够操纵结构的内容,但阻止 main 知道里面有什么。所以我想把结构定义放在a.c而不是a.h中,并将struct ctx;作为原型放在a.h中
这可以工作,但是 ctx 不能再在 main.c 的堆栈上分配,因为编译器不知道要分配的大小。
所以这引出了我的第一个问题:有没有办法在不知道结构定义的情况下将结构分配到堆栈本地。
所以我假设如果它在堆栈上是不可能的,那么也许我可以通过创建一个返回指针的简单 init 函数来将它传递到堆上。这确实有效,但是否会使过程过于复杂?
a.h
#ifndef a_h
#define a_h
#include <stdio.h>
#include <stdlib.h>
struct ctx;
int incctx(struct ctx* c);
struct ctx* initctx(void);
void destroyctx(struct ctx* c);
#endif /* a_h */
a.c
#include "a.h"
struct ctx{
int x;
};
int incctx(struct ctx* c){
return ++c->x;
}
struct ctx* initctx(){
struct ctx* c = malloc(sizeof(struct ctx));
c->x = 0;
return c;
}
void destroyctx(struct ctx* c){
free(c);
}
main.c
#include "a.h"
int main(){
struct ctx* c = initctx();
printf("%d\n",incctx(c));
printf("%d\n",incctx(c));
printf("%d\n",incctx(c));
destroyctx(c);
return 0;
}
这种设计解决了一些缺点。
1:如果我想让结构的一部分可见而不是整个东西怎么办?
2:如果我希望结构定义可用于其他文件,比如b.h 和b.c,我是否必须重新定义结构?你们中有人有更清洁的设计吗?我知道有些人说你可以在结构中放置一个 void* 而不是特定类型,然后给它们贴上任意名称,但我不认为这是一个可行的解决方案。
【问题讨论】:
-
这样的数据类型被称为opaque data types 并且很常见。有关一个非常常见的示例,请参见标准 C
FILE结构。 -
我可以看到
FILE结构的内容,我可以将它声明为堆栈本地。 -
不要在main中包含
a.h;只需定义void *ctx; -
你不应该像
FILE file;那样创建FILE类型的非指针实例。如果您可以这样做或查看成员,那么这可能是您的编译器的特定于调试的扩展。 -
是的,奇怪的是,在我的发布版本中,这段代码编译了`FILE f; fclose(&f);`