[英]function pointer in C, with or without *?
對於C中的函數指針,有沒有*之間有區別?
像我這樣的函數指針聲明
typedef void (*DListVisitNode) (Node*, void*);
void DListTraverse( NodeList* , DListVisitNode , void*);
我有這樣的代碼
void print_index( Node* node, void* ctx)
{
printf("index:%d\n", node->index);
}
void* print_content( Node* node, void* ctx)
{
printf("content:%s\n", node->content);
}
void DListTraverse(NodeList* nodelist, DListVisitNode visit_func, void* ctx)
{
Node* cur_node = nodelist->headnode;
while( cur_node != NULL)
{
visit_func( cur_node, ctx );
cur_node = cur_node->nextnode;
}
}
DListTraverse( nodelist, print_content, NULL );
DListTraverse( nodelist, print_index, NULL );
兩個DListTraverse都可以正常工作,但帶有*的那個會像這樣發出警告
warning: passing argument 2 of ‘DListTraverse’ from incompatible pointer type
之后我會刪除*,但它們之間的區別是什么?
print_content
定義為返回void*
即通用原始指針。
print_index
定義為返回void
即沒有任何結果。
這些是不同的簽名。 只有print_index
匹配DListVisitNode
。
我的編碼風格是通過typedef
定義簽名
typedef void signature_t (int);
請注意,上面沒有涉及指針。 這用一個int
參數命名函數的簽名而沒有結果。
然后,當需要指向上述簽名的這些函數的指針時,使用signature_t*
這是真的是函數的名稱就像數組的名稱; 語言隱式地將它們轉換為指針。 所以DListTraverse(nodelist, print_content, NULL)
被理解為DListTraverse(nodelist, &print_content, NULL)
您應該在編譯器上啟用所有警告; 使用gcc
意味着將-Wall -Wextra
作為編譯器的程序參數。
您已將print_content
聲明為返回void *
(指針),這意味着它與DListVisitNode
不匹配。 但是,由於函數實際上沒有返回任何內容(沒有返回語句),因此您應該再次收到警告。
您可能會對以下與typedef之間的區別感到困惑:
typedef void (*DListVisitNode) (Node*, void*);
typedef void * (*DListVisitNode) (Node*, void*);
或者等效地,在以下兩種類型之間:
void (*) (Node *, void *)
void * (*) (Node *, void *)
前者是指向返回void
的函數的指針,后者是指向返回void *
的函數的指針。 每個打印功能都是一個這樣的功能的示例。
當然,不同類型的函數指針是不兼容的,不能隱式轉換,因為這肯定沒有意義:你不能只假裝一個函數實際上有一個完全不同的簽名,並期望能夠以任何有意義的方式調用它。 這就像假裝自行車是一輛汽車,然后試圖在加油站加油。
typedef void (*DListVisitNode) (Node*, void*);
定義一個指向函數作為類型采用兩個參數Node *
和void *
,並返回一個void
。
使用上面的語句后, DListVisitNode
可以用作類型 ,確切的類型如上所述。
void* print_content( Node* node, void* ctx)
返回void *
而不是void
。
C是強類型語言,c標准規定編譯器必須報告任何類型違規,因此存在類型不匹配 ,編譯器會向您報告。 基本上,如果您的函數沒有返回任何內容,請使用返回類型作為void
或者如果您打算返回特定類型,則使用該特定類型作為返回類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.