簡體   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