简体   繁体   English

C中的函数指针,有无*?

[英]function pointer in C, with or without *?

is there difference between with or without * for function pointer in C? 对于C中的函数指针,有没有*之间有区别?

my function pointer declaration like this 像我这样的函数指针声明

typedef void (*DListVisitNode) (Node*, void*);
void DListTraverse( NodeList* , DListVisitNode , void*);

i have code like these 我有这样的代码

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 );

both of DListTraverse works, but the one with * throws warning like this 两个DListTraverse都可以正常工作,但带有*的那个会像这样发出警告

warning: passing argument 2 of ‘DListTraverse’ from incompatible pointer type

i would simply delete the * afterward, but what's the difference between them? 之后我会删除*,但它们之间的区别是什么?

print_content is defined as returning a void* ie a generic raw pointer. print_content定义为返回void*即通用原始指针。

print_index is defined as returning void ie without any results. print_index定义为返回void即没有任何结果。

These are different signatures. 这些是不同的签名。 Only print_index matches DListVisitNode . 只有print_index匹配DListVisitNode

My coding style is to define signature thru typedef like 我的编码风格是通过typedef定义签名

  typedef void signature_t (int);

Notice that no pointer is involved above. 请注意,上面没有涉及指针。 This names the signature of functions with one int argument and no results. 这用一个int参数命名函数的签名而没有结果。

then, when needing pointers to such functions of above signature, use signature_t* 然后,当需要指向上述签名的这些函数的指针时,使用signature_t*

What is true is that the name of a function is like the name of an array; 这是真的是函数的名称就像数组的名称; the language implicitly convert these to pointers. 语言隐式地将它们转换为指针。 So DListTraverse(nodelist, print_content, NULL) is understood like DListTraverse(nodelist, &print_content, NULL) 所以DListTraverse(nodelist, print_content, NULL)被理解为DListTraverse(nodelist, &print_content, NULL)

You should enable all warnings on your compiler; 您应该在编译器上启用所有警告; with gcc that means giving -Wall -Wextra as program arguments to the compiler. 使用gcc意味着将-Wall -Wextra作为编译器的程序参数。

You've declared print_content as returning a void * (a pointer), which means it doesn't match DListVisitNode . 您已将print_content声明为返回void * (指针),这意味着它与DListVisitNode不匹配。 However, as the function doesn't actually return anything (no return statement), you should be gatting another warning about that. 但是,由于函数实际上没有返回任何内容(没有返回语句),因此您应该再次收到警告。

You may be confused about the difference between the following to typedefs: 您可能会对以下与typedef之间的区别感到困惑:

typedef void (*DListVisitNode) (Node*, void*);
typedef void * (*DListVisitNode) (Node*, void*);

Or equivalently, between the following two types: 或者等效地,在以下两种类型之间:

  • void (*) (Node *, void *)

  • void * (*) (Node *, void *)

The former is a pointer to a function returning void , the latter is a pointer to a function returning void * . 前者是指向返回void的函数的指针,后者是指向返回void *的函数的指针。 Each of your print functions is an example of one such function. 每个打印功能都是一个这样的功能的示例。

Naturally, function pointers of different types are incompatible and not implicitly convertible, as surely this would make no sense: You can't just pretend that a function actually has a completely different signature and expect to be able to call it in any meaningful way. 当然,不同类型的函数指针是不兼容的,不能隐式转换,因为这肯定没有意义:你不能只假装一个函数实际上有一个完全不同的签名,并期望能够以任何有意义的方式调用它。 It would be like pretending that a bicycle is a car and then trying to refuel it at a gas station. 这就像假装自行车是一辆汽车,然后试图在加油站加油。

typedef void (*DListVisitNode) (Node*, void*);     

Defines a pointer to an function as an type which takes two parameters Node * and void * and returns a void . 定义一个指向函数作为类型采用两个参数Node *void * ,并返回一个void
Once you use the above statement, DListVisitNode can be used as an type , the exact type is as mentioned above. 使用上面的语句后, DListVisitNode可以用作类型 ,确切的类型如上所述。

void* print_content( Node* node, void* ctx) 

returns a void * and not a void . 返回void *而不是void
C is a strongly typed language, the c standard mandates that any type violations must be reported by the compiler, hence there is a type mismatch and the compiler reports it to you. C是强类型语言,c标准规定编译器必须报告任何类型违规,因此存在类型不匹配 ,编译器会向您报告。 Basically, if your function doesn't return anything use the return type as void or if you intend to return a particular type then use that specific type as an return type. 基本上,如果您的函数没有返回任何内容,请使用返回类型作为void或者如果您打算返回特定类型,则使用该特定类型作为返回类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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