我知道可能曾经有人问过这个问题,但我想采取自己的方法,并征求意见或采取更好的方法。
我有三个文件a.h
a.c
和main.c
有关该结构的函数的原型在a.h
中,而实现的原型在a.c
中,并从{{1 }}结构会很简单,就像这样
main.c
我希望struct ctx{
int x;
};
能够操纵该结构的内容,但要防止main对内部内容有任何了解。因此,我想到了将结构定义放在a.c
而不是a.c
中,并且只将a.h
作为原型放在struct ctx;
中
这可能行得通,但是ctx不能再在a.h
中的堆栈中分配,因为编译器不知道要分配的大小。
因此,这引出了我的第一个问题:是否有一种方法可以在不知道结构定义的情况下在堆栈中分配本地结构。
所以我假设如果在堆栈上不可能,那么我可以将其传递到堆上,而不是通过创建一个简单的返回指针的init函数。确实可行,但这是否会使流程复杂化?
main.c
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
这种设计解决了一些缺点。
1:如果我想使结构的一部分可见而不是整个东西怎么办?
2:如果我希望结构定义可用于其他文件,请说#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;
}
和b.h
,我是否需要重新定义结构?你们有没有更干净的设计?我知道有人说您可以在结构中放置b.c
而不是特定类型,然后将它们标记为任意名称,但我认为这不是可行的解决方案。
答案 0 :(得分:5)
对于可见性问题,您可以采用类似继承的方式使用两个结构。
首先,您具有在头文件中定义的公共结构,并且您的API将处理该公共结构:
struct ctx
{
// Public data
};
然后在源文件中创建一个私有结构,其中公共结构是第一个成员:
struct private_ctx
{
struct ctx ctx; // The public part of the structure
// Followed by private data
};
在API内部,您使用private_ctx
结构,而使用API的代码将仅使用公共ctx
结构。
这样的嵌套结构与继承类似,private_ctx
结构是 ctx
结构。您可以创建一个private_ctx
结构,并返回一个指向它的指针,该指针适当地转换为ctx
结构。
以下是有关如何创建结构的示例:
struct ctx *create_struct(void)
{
// Allocate the private structure, which contains the public structure
struct private_ctx *data = = malloc(sizeof *data);
// Return the public part of the structure
return (struct ctx *) data;
}
使用私有数据通过反向强制转换同样容易:
void use_data(struct ctx *data)
{
struct private_ctx *private_data = (struct private_ctx *) data;
// Here the private data can be used...
}
答案 1 :(得分:4)
抽象隐藏可以通过让模块向main传递指向该结构的指针并让您的模块对它进行所有操作来实现。那么main仅知道ctx
是某种无效数据类型(指针)就足够了,例如
// main.c
void *initctx(void);
int incctx(void *c);
int main(void)
{
void *ctx= initctx();
int i= incctx(ctx);
//....
}
答案 2 :(得分:0)
您想将整个结构隐藏在a.c中
分配结构时,不要返回指向它的指针,而是返回一个句柄,该句柄可能是您在a.c中维护的结构数组的索引。
如果要将结构的任何部分暴露在外面,请提供诸如getSomething(int handle)或setSomething(int handle)之类的功能。
open(),返回一个int使用此方法,而fopen()返回一个FILE *