【发布时间】:2015-09-29 15:02:18
【问题描述】:
假设你有一个相当复杂的函数签名,像这样:
void **search( char *inSearch, int inNumToSkip,
int inNumToGet, int *outNumResults, int *outNumRemaining );
假设您要编写另一个函数,该函数接受指向与此“搜索”签名匹配的函数的指针。在示例中,我通常会看到这样编写的函数:
void *getFirstResult( char *inSearch,
void ** (inSearchFunc*)( char *, int, int, int*, int* ) );
假设这个函数使用传入的函数执行搜索并只返回第一个结果,干净地破坏其余的,或者其他什么。
现在,查看 getFirstResult 并尝试编写一个函数来传递给它,它完全是非自文档化的,因为该定义中没有包含有关“inSearchFunc”参数的信息。你知道它是某种类型的搜索功能,但没有别的。
请注意,相同的格式(没有名称的参数类型)在标头或前向声明中作为函数原型是有效的,因此参数名称始终是可选的,即使在实际的函数实现中(显然需要使用它们)函数体中的参数,但仍然是可选的)。
我在任何地方都找不到它的文档或提及,但它可以编译并正常工作:
void *getFirstResult( char *inSearch,
void ** (inSearchFunc*)( char *inSearch,
int inNumToSkip,
int inNumToGet,
int *outNumResults,
int *outNumRemaining ) );
这显然更加清晰和自我记录。
这是合法且安全的 C 代码吗?这种可选语法记录在哪里?
最后,为什么不是每个人都这样写他们的函数指针参数为了清楚起见?尤其是在旨在向初学者解释函数指针的示例中,无名参数看起来总是完全不透明且令人困惑。
其实这个超级不透明的版本也是合法的:
void *getFirstResult( char *,
void ** (*)( char *, int, int, int*, int* ) );
显然,为了清楚起见,每个人至少都会给 char * 和 (*) 起一个名字,那么为什么不给所有东西起一个名字呢?
在我古老的C++ Primer中,它说:
函数声明中不需要参数名称。如果存在,则其名称应作为文档辅助。
然后
在同一函数的声明和定义中为参数指定不同的名称不会受到语言惩罚。但是,该程序的读者可能会感到困惑。
【问题讨论】:
-
"显然,每个人至少都会给..." 不。
-
"这是合法且安全的 C 代码吗?" 是的。
-
"你知道它是某种类型的搜索功能,但没有别的。" 要么阅读源代码,要么阅读文档。或者两者都读。如果两者都不可用,则不要使用该功能。
-
原型声明中的参数名称与实际函数定义中的参数名称不必有任何关系,可以省略。为了一致性起见,如果没有别的,要么全部命名,要么不命名。另见Where to document functions in C?
getFirstResult()函数声明的标头应该足够解释如何使用它,这肯定会涉及到回调函数指针的解释。
标签: c