我的一个朋友试图用C测试我(我最强的语言是C ++),他问我三个我无法回答的问题:
尝试解释以下声明:
1) int (*x)(int, char *, void *);
2) int (*x[10])(int, char *, void *);
3) int (**x[10])(int, char *, void *);
任何人都可以解释这些函数声明并解释正在使用的概念吗?
答案 0 :(得分:31)
您需要cdecl
计划,这将为您提供明确,正确的答案。学习如何手动解释这些语句是可行和有益的,但即便如此,cdecl对于检查你是否有正确的答案非常有用。
prompt>cdecl
Type `help' or `?' for help
cdecl> explain int (*x)(int, char *, void *);
declare x as pointer to function (int, pointer to char, pointer to void) returning int
cdecl> explain int (*x[10])(int, char *, void *);
declare x as array 10 of pointer to function (int, pointer to char, pointer to void) returning int
cdecl> explain int (**x[10])(int, char *, void *);
declare x as array 10 of pointer to pointer to function (int, pointer to char, pointer to void) returning int
cdecl>
答案 1 :(得分:21)
嗯,第一个是指向函数的指针。换句话说,它声明了一个变量“x”,它指向以下类型的函数:
int function(int, char*, void*);
可以使用如下:
int myfunc(int a, char* b, void* c) {
return a;
}
void acallingfunction() {
int (*x)(int, char*, void*);
x = myfunc;
x(1, "hello", 0);
}
第二个似乎是无效的语法,但我可能是错的。如果它在x之前有一个星号(例如int(* x [10])(int,char *,void *)),它将是一个函数指针数组,并且将像普通数组一样使用:
x[3](1, "Hi there", 0);
第三个是指向函数指针的指针数组,这看似不实用,但完全有效。示例用法可能是:
void anothercaller() {
int (*x)(int, char*, void*);
int (**y)(int, char*, void*);
x = myfunc;
y = &x;
(*y)(1, "hello", 0);
}
请注意,其中前两个比较常见。指向函数的指针用于在C中完成回调和各种面向对象的编程概念。函数指针数组可用于事件表,以找到适当的回调。
请注意,所有这些实际上都是有效的C ++。 ;)
编辑:我显然犯了void main()的暴行。
编辑2:正如Chris Lutz在下面指出的那样,他们真的应该用typedef包装。 Typedef使包含函数指针的代码更加清晰。
答案 2 :(得分:7)
答案 3 :(得分:6)
如上所述,它们是函数指针,但写得相当令人讨厌(在我看来)。我写它们的方式是:
typedef int (*funcptr)(int, char *, void *);
funcptr x;
funcptr x[10];
funcptr *x;
有关函数指针的更多信息,请参阅Walt W's excellent answer。
答案 4 :(得分:3)
由于C的语法就像这个问题中的C ++,geordi对你来说很有意思。它是另一个用于教授和学习这些声明的好工具(以及与C ++相关的其他事情,有时也与C相关)。
geordi: << ETYPE_DESC(x); int (*x)(int, char *, void *);
lvalue pointer to a function taking an integer, a pointer to a character, a pointer to anything, and returning an integer
geordi: << ETYPE_DESC(x); int (*x[10])(int, char *, void *);
lvalue array of 10 pointers to functions taking an integer, a pointer to a character, a pointer to anything, and returning integers
geordi: << ETYPE_DESC(x); int (**x[10])(int, char *, void *);
lvalue array of 10 pointers to pointers to functions taking an integer, a pointer to a character, a pointer to anything, and returning integers
正如其页面所解释的,它可以做更多事情,包括为你构建一个类型
geordi: make type array of 10 pointers to functions taking an integer and returning void
void(*[10])(int)
如果你原则上知道如何宣布事情,但不确定一件事,你可以使用括号:
geordi: make type ( void(int, bool) )*
void(*)(int, bool)
如果您想查看其中包含标识符的情况,您也可以更改名称类型
geordi: -c int x;
Success
geordi: make x a ( void(int, bool) )* and show
-c void (* x)(int, bool) ;
如果你建立了一个声明,但是你不确定运算符的优先级,那么geordi的优先级函数可以帮助你
geordi: precedence *x(a, b)
*(x(a, b))