[英]Messy function pointer : how to remove the warning?
正如我在这篇文章中提到并回答的那样。 我有以下示例代码。
#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(带有“警告:从不兼容的指针类型返回”)和
回归和娱乐两者都有效?
警告:从不兼容的指针类型分配。 如何删除此警告?
有了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]());
}
您必须决定是使用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
内容与原始帖子中的内容相同。 换句话说,您的原始代码是两种不同的绝对不兼容技术的奇异融合。 您必须决定要使用哪一个并坚持下去。
我建议你输入你的函数指针,否则很难看出发生了什么。
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();
对于第一个问题,
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的函数的指针数组。 通过添加&,您现在实际上返回指向返回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
在x
的返回类型中选择额外的*
或[]
,而不是两者。
当你做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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.