在C中隐藏类型定义

时间:2012-02-13 23:35:20

标签: c types interface struct typedef

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

typedef long double big;
big foo(int x) { ... }

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

typedef long double big;
big foo(int);

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

我知道我可以在.c文件中执行此操作:

struct foo {
  long double;
};

然后在.h文件中执行:

typedef struct foo big;
big foo(int);

但仅为一个字段创建struct似乎很浪费,而且每当我想要阅读.时,我都应该使用big运算符。

2 个答案:

答案 0 :(得分:4)

如果类型永远不会比long double更复杂,那么关于隐藏它的可能性并不值得。如果它可能需要变得更复杂,那么您可以考虑使用opaque类型。在公共标题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结构内乱搞。但请注意,您必须在界面中使用指针。传递或返回值需要完整的类型,如果类型完整,用户可以调查其内部工作。

在实施标题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。这里的主要问题是确保你知道如何处理内存分配。

有时这种技术是值得的。通常没有必要。你需要自己做评估。

答案 1 :(得分:2)

  

并删除typedef long double big;来自.c文件。但通过这样做,我在我的界面中放弃了big的类型定义,所以它并不是一个干净的界面。

怎么样?谁在乎你的代码用户是否能看到typedef?怎么伤害......什么?他们需要一种方法来使用你的typedef,这就是它的完成方式。听起来像是一个没有明显不良影响的理论问题。你担心错误的事情。

  

但是山雀似乎很浪费为一个领域创建一个结构,而且我应该使用。操作员每当我想读一个大的。

是的,这很傻。此外,现在你已经放弃了你的结构的定义!不好了!与暴露typedef(或任何其他类型)有何不同?