Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的函数指针,带或不带*?_C_Function Pointers - Fatal编程技术网

C中的函数指针,带或不带*?

C中的函数指针,带或不带*?,c,function-pointers,C,Function Pointers,对于C中的函数指针,带*和不带*有区别吗 我的函数指针声明如下 typedef void (*DListVisitNode) (Node*, void*); void DListTraverse( NodeList* , DListVisitNode , void*); warning: passing argument 2 of ‘DListTraverse’ from incompatible pointer type 我有这样的代码 void print_index( Node* no

对于C中的函数指针,带*和不带*有区别吗

我的函数指针声明如下

typedef void (*DListVisitNode) (Node*, void*);
void DListTraverse( NodeList* , DListVisitNode , void*);
warning: passing argument 2 of ‘DListTraverse’ from incompatible pointer type
我有这样的代码

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都可以工作,但是带有*的那个会抛出如下警告

typedef void (*DListVisitNode) (Node*, void*);
void DListTraverse( NodeList* , DListVisitNode , void*);
warning: passing argument 2 of ‘DListTraverse’ from incompatible pointer type

我只想在之后删除*,但它们之间有什么区别?

print\u content
定义为返回一个
void*
,即一个通用的原始指针

print_index
定义为返回
void
,即没有任何结果

这些是不同的签名。只有
print\u index
匹配
DListVisitNode

我的编码风格是通过
typedef
like定义签名

  typedef void signature_t (int);
请注意,上面没有涉及任何指针。这将命名具有一个
int
参数且没有结果的函数签名

然后,当需要指向上述签名的函数的指针时,使用
signature\u t*

真正的情况是,函数的名称类似于数组的名称;语言隐式地将这些转换为指针。因此
DListTraverse(nodelist,print\u content,NULL)
被理解为
DListTraverse(nodelist,print\u content,NULL)


您应该在编译器上启用所有警告;使用
gcc
意味着将
-Wall-Wextra
作为程序参数提供给编译器。

您已声明
print\u content
为返回
void*
(指针),这意味着它与
DListVisitNode
不匹配。但是,由于函数实际上不返回任何内容(no return语句),因此您应该对此发出另一个警告

typedef void (*DListVisitNode) (Node*, void*);     
将指向函数的指针定义为类型,该类型接受两个参数
Node*
void*
,并返回一个
void

使用上述语句后,
DListVisitNode
可以用作类型,确切的类型如上所述

void* print_content( Node* node, void* ctx) 
返回一个
void*
而不是
void


C是一种强类型语言,C标准要求编译器必须报告任何类型冲突,因此存在类型不匹配,编译器会向您报告。基本上,如果您的函数不返回任何内容,请使用返回类型作为
void
,或者如果您打算返回特定类型,请使用该特定类型作为返回类型。

您可能会对以下与typedefs之间的差异感到困惑:

typedef void (*DListVisitNode) (Node*, void*);
typedef void * (*DListVisitNode) (Node*, void*);
或等效地,在以下两种类型之间:

  • void(*)(节点*,void*)

  • void*(*)(节点*,void*)

前者是指向返回
void*
的函数的指针,后者是指向返回
void*
的函数的指针。每个打印函数都是此类函数的一个示例


当然,不同类型的函数指针是不兼容的,不能隐式转换,因为这毫无意义:你不能假装一个函数实际上有一个完全不同的签名,并期望能够以任何有意义的方式调用它。这就像假装自行车是汽车,然后试图在加油站给它加油。

您交换了功能。匹配
DListVisitNode
:)的是
print\u index