在 C 中隐藏类型定义

Foo*_* R. 0 c struct types typedef interface

我有一个.c带有函数和定义的文件(函数库),如下所示:

typedef long double big;
big foo(int x) { ... }
Run Code Online (Sandbox Code Playgroud)

我想创建这个库的一个接口,一个.h. 所以我这样做:

typedef long double big;
big foo(int);
Run Code Online (Sandbox Code Playgroud)

typedef long double big;.c文件中删除。但是通过这样做,我放弃了big接口中的类型定义,所以它并不是一个真正干净的接口。任何想法如何解决这个问题?

我知道我可以在我的.c文件中做到这一点:

struct foo {
  long double;
};
Run Code Online (Sandbox Code Playgroud)

然后在.h文件中做:

typedef struct foo big;
big foo(int);
Run Code Online (Sandbox Code Playgroud)

但是struct只为一个字段创建一个似乎很浪费,而且.每当我想读取big.

Jon*_*ler 5

如果类型永远不会变得比 更复杂long double,那么可能不值得对更多地隐藏它。如果它可能需要变得更复杂,那么您可以考虑使用不透明类型。在您的公共标题中big.h,您使用:

#ifndef BIG_H_INCLUDED
#define BIG_H_INCLUDED
typedef struct big big_t;

extern big_t *foo(int);

...

#endif
Run Code Online (Sandbox Code Playgroud)

所有函数都将获取并返回指向该big_t类型的指针。这就是你可以对这样的不完整类型做的所有事情。请注意,您的客户不能big_t为自己分配任何价值;他们不知道这种类型有多大。这意味着您可能最终会得到以下功能:

extern big_t *big_create(void);
extern void   big_destroy(big_t *value);
Run Code Online (Sandbox Code Playgroud)

创造和摧毁big_t价值。然后他们将能够进行算术运算:

extern big_errno_t big_add(const big_t *lhs, const big_t *rhs, big_t *result);
Run Code Online (Sandbox Code Playgroud)

等等。但是因为它们只有一个不透明的、不完整的类型,所以它们不能可靠地在big_t结构内部乱搞。但请注意,您只能在接口中使用指针。传递或返回值需要完整的类型,如果类型完整,用户可以调查其内部工作原理。

在实现标头 中bigimpl.h,您将拥有:

#ifndef BIGIMPL_H_INCLUDED
#define BIGIMPL_H_INCLUDED
#include "big.h"

struct big
{
    ...whatever the details actually are...
};

#endif
Run Code Online (Sandbox Code Playgroud)

并且您的实现代码只会包含bigimpl.h,但包含big.h. 这里的主要问题是确保您知道如何处理内存分配。

有时这种技术是值得的。很多时候并不是真的有必要。您需要自己进行评估。