繁体   English   中英

凌乱的函数指针:如何删除警告?

[英]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(带有“警​​告:从不兼容的指针类型返回”) 
      回归和娱乐 
    两者都有效?
  • 我在第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]()); 
}

您必须决定是使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM