编辑:将foo_t改为foo作为类型名,因为POSIX保留以_t结尾的类型,编辑:将_foo_s更改为foo_s,因为C声明名称以下划线开头
我对同时拥有以下内容的最佳方式感到困惑:
我第一次尝试这样做是为了做以下工作:
foo.h (为了简洁起见省略了包含警卫):
typedef struct foo_s foo;
struct foo_s;
foo* foo_create(void);
void foo_do_something(foo *foo);F.c:
#include "foo.h"
struct foo_s {
/* some_hidden_members */
};
foo* foo_create() {
/* allocate memory etc */
}
void foo_do_something(foo *foo) {
/* do something with foo */
}这似乎适用于gcc。每个包括foo.h的人都只看到匿名转发声明,而struct foo_s的真正布局只在foo.c中已知。
当我尝试使用使用clang的包含-什么-你-使用时,我开始用上面提到的奇怪的东西。当我使用它检查foo.c时,它告诉我foo.h不应该包含struct foo_s的前向声明。我认为这是iwyu中的一个bug,因为显然这对包括foo.h的其他任何人来说都不是问题。
在这一点上,让我从一开始谈我的第二个要求。foo.c包括foo.h,以便编译器能够确保foo.h中声明的每个函数都与foo.c中的实现匹配。我认为我需要这样做,因为我经常遇到分段错误,因为我的实现的函数签名与其他代码使用的标头中的函数签名不匹配。
后来,我尝试用clang编译代码(我用-Wall -Wextra -Werror编译),并被告知:
error: redefinition of typedef 'foo' is a C11 feature我不希望我的代码依赖于C11特性,我确实希望确保公共标题中的函数与实现匹配。我该怎么解决呢?
我看到了一种将foo.h分解成foo.h和foo_private.h的方法
foo.h (为了简洁起见省略了包含警卫):
struct foo_s;
#include "foo_private.h"foo_private.h (为了简洁起见省略了包含保护):
typedef struct foo_s foo;
foo* foo_create(void);
void foo_do_something(foo *foo);然后,我将在foo_private.h中包括foo.c,其他代码将包括foo.h。这意味着foo.c不再看到foo_s的前向声明,因此clang和iwyu应该很高兴。这还意味着检查我的函数的实现以匹配标头。
但是,虽然这是可行的,但我想知道这是否是最好的解决办法,因为:
那么,怎样的解决方案才能满足上面列出的三个标准呢?还是我找到了解决办法?
发布于 2014-09-19 18:10:57
荣誉对数据隐藏的崇高意图!
下面这个怎么样?
foo.h (为简洁起见省略了包含保护):
typedef struct foo_t foo_t; // note change 0
// note change 1
foo_t* foo_create(void);
void foo_do_something(foo_t *foo);foo.c:
#include "foo.h"
struct foo_t { // note change 2
/* some_hidden_members */
};
foo_t* foo_create() {
/* allocate memory etc */
}
void foo_do_something(foo_t *foo) {
/* do something with foo */
}https://stackoverflow.com/questions/25939478
复制相似问题