正如我在this post中提出并回答的那样。我有以下示例代码。
#include <stdio.h>
char foo() { return 'a'; }
char bar() { return 'b'; }
char blurga() { return 'c'; }
char bletch() { return 'd'; }
char (*gfunclist[])() = {foo, bar, blurga, bletch};
char (*(*x())[])()
{
static char (*funclist[4])() = {foo, bar, blurga, bletch};
return funclist;
}
int main()
{
printf("%c\n",gfunclist[0]());
char (**fs)();
fs = x();
printf("%c\n",fs[1]());
}
我的问题是
return funclist (with "warning: return from incompatible pointer type")和
return &funclist都有效?
warning: assignment from incompatible pointer type的第21行(fs = x();)收到警告。如何删除此警告?
在AndreyT的帮助下。我可以得到以下没有警告的代码。
#include <stdio.h>
char foo() { return 'a'; }
char bar() { return 'b'; }
char blurga() { return 'c'; }
char bletch() { return 'd'; }
char (*gfunclist[])() = {foo, bar, blurga, bletch};
char (*(*x())[])()
{
static char (*funclist[4])() = {foo, bar, blurga, bletch};
return &funclist;
}
int main()
{
printf("%c\n",gfunclist[0]());
char (*(*fs)[4])();
fs = x();
printf("%c\n",(*fs)[1]());
}
在peoro的帮助下,这是一个不那么混乱的代码。
typedef char (*funptr)();
funptr gfunclist[] = {foo, bar, blurga, bletch};
funptr* x()
{
static funptr funclist[4] = {foo, bar, blurga, bletch};
return funclist;
}
int main()
{
printf("%c\n",gfunclist[0]());
funptr *fs;
fs = x();
printf("%c\n",fs[1]());
}
答案 0 :(得分:3)
您必须决定是使用C还是C ++。这些语言在处理像你这样的情况时有很大的不同。
在C ++中,“指向[]
数组的指针”(即未指定大小的数组)是与“指向[N]数组的指针”(即指定大小的数组)完全不同的类型。这立即意味着您的代码无法编译为C ++代码。它不是“警告”,而是一个错误。如果希望代码编译为C ++,则需要在函数返回类型中指定确切的数组大小
char (*(*x())[4])() // <- see the explicit 4 here?
{
static char (*funclist[4])() = {foo, bar, blurga, bletch};
return &funclist;
}
当然,你必须返回&funclist
,因为你声明你的函数是返回指向数组的指针。
在main
中将接收指针声明为char (**fs)()
毫无意义。该函数返回一个指向数组的指针,而不是指向的指针。您需要将fs
声明为
char (*(*fs)[4])(); // <- pointer to an array
即。具有指向数组的指针类型(注意与函数声明的相似性)。并且为了通过这样的指针调用函数,你必须做
printf("%c\n", (*fs)[1]());
在C语言中,指针到数组声明中的显式数组大小可以省略,因为在C“指向[]数组的指针”类型与“指向[N]数组的指针”类型兼容,但是其他观点仍然有效。但是,即使在C中,明确指定该大小也可能更有意义。
或者,您可以停止使用指针到数组类型,而是使用指针到指针类型。在这种情况下,您的函数应定义如下
char (**x())()
{
static char (*funclist[4])() = {foo, bar, blurga, bletch};
return funclist; // <- no `&` here
}
并在main
中,您将按照以下方式使用
char (**fs)();
fs = x();
printf("%c\n", fs[1]());
请注意,此main
与您原始帖子中的内容相同。换句话说,您的原始代码是两种不同的绝对不兼容技术的奇异融合。你必须决定使用哪一个并坚持下去。
答案 1 :(得分:2)
我建议你输入你的函数指针,否则很难看出发生了什么。
typedef char (*funptr)();
无论如何,x
会返回指向char (*(*x())[])
的指针,funclist
不是那个。
fs=x();
:char ((())[]) != char (**)();
...
如果我没错,那么[]和* ...
之间也会出现一些优先级错误这很好用:
typedef char (*funptr)();
funptr gfunclist[] = {foo, bar, blurga, bletch};
funptr *x() {
static funptr funclist[4] = {foo, bar, blurga, bletch};
return funclist;
}
funptr *fs;
fs = x();
答案 2 :(得分:1)
对于第一个问题,
cdecl> explain char (*(*x())[])()
declare x as function returning pointer to array of pointer to function returning char
cdecl> explain static char (*funclist[4])()
declare funclist as static array 4 of pointer to function returning char
所以x的预期返回类型是指向返回char的函数的指针数组的指针,但是你返回的只是返回char的函数的指针数组。通过添加&amp;,您现在实际上返回指向返回char的函数的指针数组的指针。
对于第二个,x的预期返回类型再次是指向返回char的函数的指针数组的指针,但我们看到
cdecl> explain char (**fs)();
declare fs as pointer to pointer to function returning char
您想要的是char (*(*fs)[])();
cdecl> explain char (*(*fs)[])();
declare fs as pointer to array of pointer to function returning char
答案 3 :(得分:1)
在*
的返回类型中选择额外的[]
或x
,而不是两者。
答案 4 :(得分:1)
执行T a[] = { .. };
后,a
被声明为T[N]
类型,但不是类型T[]
。
所以你需要在括号中加上一些数字。
char (*(*x())[sizeof(gfunclist)/sizeof(*gfunclist)])()
{
return &gfunclist;
}
它会限制您可以返回到特定大小的内容。这是C ++与C的不同之处,它允许您将T(*)[N]
分配给T(*)[]
。 C ++没有这种所谓的“类型兼容性”规则。如果你想摆脱&
的需要,你需要返回数组的衰变类型。数组的元素类型是char(*)()
char (**x())()
{
static char (*funclist[4])() = {foo, bar, blurga, bletch};
return funclist;
}
使用身份模板可以使您的声明看起来更具可读性
template<typename T> struct identity { typedef T type; };
identity<char()>::type **x()
{
static identity<char()>::type *funclist[] = {foo, bar, blurga, bletch};
return funclist;
}