我有一个 .c
文件(函数库),其中包含一个函数和如下定义:
typedef long double big;
big foo(int x) { ... }
我想为这个库创建一个接口(interface),一个.h
。所以我这样做:
typedef long double big;
big foo(int);
并从 .c
文件中删除 typedef long double big;
。但是通过这样做,我在我的界面中放弃了 big
的类型定义,所以它并不是一个真正干净的界面。有什么解决办法吗?
我知道我可以在我的 .c
文件中这样做:
struct foo {
long double;
};
然后在.h
文件中做:
typedef struct foo big;
big foo(int);
但是只为一个字段创建一个 struct
似乎很浪费,而且我应该使用 .
运算符,每当我想读取一个 big
.
最佳答案
如果类型永远不会变得比long double
更复杂,那么可能不值得再花心思去隐藏它。如果它可能需要变得更复杂,那么您可以考虑使用不透明类型。在您的公共(public) header big.h
中,您使用:
#ifndef BIG_H_INCLUDED
#define BIG_H_INCLUDED
typedef struct big big_t;
extern big_t *foo(int);
...
#endif
所有函数都将获取并返回指向 big_t
类型的指针。这就是您可以对此类不完整类型所做的全部工作。请注意,您的客户不能为自己分配任何 big_t
值;他们不知道这种类型有多大。这意味着您最终可能会得到如下函数:
extern big_t *big_create(void);
extern void big_destroy(big_t *value);
创建和销毁 big_t
值。然后他们将能够使用以下方法进行算术运算:
extern big_errno_t big_add(const big_t *lhs, const big_t *rhs, big_t *result);
等等。但是因为它们只有一个不透明的、不完整的类型,所以它们不能可靠地在 big_t
结构中乱搞。但请注意,您只能在界面中使用指针。传递或返回值需要完整的类型,如果类型完整,用户可以调查其内部工作原理。
在实现 header bigimpl.h
中,您将拥有:
#ifndef BIGIMPL_H_INCLUDED
#define BIGIMPL_H_INCLUDED
#include "big.h"
struct big
{
...whatever the details actually are...
};
#endif
您的实现代码将只包含 bigimpl.h
,但包含 big.h
。这里的主要问题是确保您知道内存分配是如何处理的。
有时这种技术是值得的。通常这并不是真正必要的。您需要自己进行评估。
关于c - 在 C 中隐藏类型定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9269691/