【发布时间】:2017-12-02 01:35:42
【问题描述】:
我可以声明一个 不透明 函数指针类型,没有完整的原型,并初始化一个包含指向该类型函数的指针的结构,而不充实签名(将在使用点)。
例如:
// file api.h
typedef void (*function_ptr)(???);
typedef struct {
function_ptr func;
} S;
function_ptr foo;
function_ptr bar;
const S structs[] = { {foo}, {bar} };
// file impl.c
typedef ret_type (*function_ptr)( // complex argument list );
void foo( // complex argument list) {
...
}
void bar( // complex argument list) {
...
}
structs[0].func(arg1, arg2, arg3);
基本上我想从api.h 头文件中隐藏函数原型的细节(返回类型和参数列表),但仍然声明使用指向该函数的指针的structs。在任何此类函数的声明位置或它们的使用位置,完整的原型应该在范围内,并且将进行参数检查等。
类似的模式适用于前向声明的结构:您可以前向声明一个不透明的struct C,并在其他结构中使用指向该结构的指针,包括静态初始化指向C 的指针,例如:
struct C;
typedef struct {
struct C* c;
} D;
extern struct C c;
D d[] = {
{ &c }
};
C 的详细信息完全隐藏。我正在寻找函数指针的等效模式。
【问题讨论】:
-
函数槽的什么属性需要在文件外可见?只是它占用了结构中的空间,并且您希望它在已知实际类型的文件中进行类型检查?
-
@ZalmanStern - 正确。所有函数指针都可以转换为所有其他指针,因此不应该有任何类型的“改变指针大小”行为需要处理。
-
const S structs[] = { {foo}, {bar} };是一个错误:静态变量的初始化程序必须是常量表达式。此外,它还会导致在标题中出现多重定义错误。 -
@M.M - 对,事实上定义实际上是在
.c文件中。是的,{foo}东西不起作用,但考虑到我想做的那种文件的伪代码,因为我不知道正确的语法(如果foo是一个函数,它肯定会起作用,例如. -
@ZalmanStern - 我认为您不能安全地将函数指针转换为
void *并再次返回。指向函数的指针和指向其他所有内容的指针不一定具有相同的表示或大小。也就是说,我提出了一个解决方案 below - 但它是任意函数指针类型(void (*)(void)以避免该问题。
标签: c function-pointers