【问题标题】:the difference between void (*xmlHashScanner) and void *xmlHashScannervoid (*xmlHashScanner) 和 void *xmlHashScanner 的区别
【发布时间】:2016-08-01 15:10:06
【问题描述】:

C 中的void (*xmlHashScanner)(void *payload, void *data, xmlChar *name)void *xmlHashScanner(void *payload, void *data, xmlChar *name) 有什么区别?
为什么它们的行为不同?


xmlHashScanner 是库 libxml2 中的用户定义函数。
当我尝试使用稍微不同的原型重新定义此函数时:void *xmlHashScanner 而不是 void (*xmlHashScanner) 我有以下错误:

error: ‘xmlHashScanner’ redeclared as different kind of symbol
 void *xmlHashScanner(void *payload, void *data, xmlChar *name)
       ^
In file included from /usr/include/libxml2/libxml/parser.h:18:0,
                 from /home/solar/Bureau/parser/src/diam_dict.c:12:
/usr/include/libxml2/libxml/hash.h:88:16: note: previous declaration of ‘xmlHashScanner’ was here
 typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name);

我想知道他们两个有什么区别。

【问题讨论】:

  • 你能解释一下不同的行为吗?
  • @ScottHunter 我说它们是不同的,因为一个编译而另一个不编译。
  • void (*xmlHashScanner)() 是一个指向 void 函数的指针。 void *xmlHashScanner() 是一个返回 void 指针的函数。
  • @Arkadiy 指向 void 函数的指针有什么用?第一个返回什么?
  • 你完全迷路了。我知道您的问题出在哪里,但是您提出问题的方式无法明智地回答。请提供MCVE。至于函数的用途,你可以试试你正在使用的 API 的the docs。这是一个回调声明。有些函数需要一个函数指针作为参数。然后,他们将“回调”您的功能,作为其操作的一部分。 Are you on the same course?

标签: c


【解决方案1】:

void (*xmlHashScanner)(...) 是函数指针的原型,它什么都不返回 (void),而 void *xmlHashScanner(...) 是函数指针的原型,它返回一个 void*

【讨论】:

    【解决方案2】:
    void (*xmlHashScanner)(void *payload, void *data, xmlChar *name)
    

    xmlHashScanner声明为一个指向函数的指针返回void,而

    void *xmlHashScanner(void *payload, void *data, xmlChar *name)
    

    xmlHashScanner 声明为返回指向void 的指针的函数。

    在声明和表达式语法中,一元 * 运算符的优先级低于后缀 [] 下标和 () 函数调用运算符,所以

    T *a[N];     // a is an N-element array of pointer to T
    T (*a)[N];   // a is a pointer to an N-element array of T
    T *f();      // f is a function returning a pointer to T
    T (*f)();    // f is a pointer to a function returning T
    

    【讨论】:

    • 我以为我学到了很多关于c的知识,但是现在我觉得我才发现了它的%0.1……还有很长的路要走。
    • @cheater:有关声明语法的完整描述,请参见 C 标准的latest online draft 的第 6.7 节。 6.7.6(声明符)是事情变得非常丑陋的地方^H^H^H^H有趣。
    【解决方案3】:

    所以你在比较这个:

    void *xmlHashScanner(void *payload, void *data, xmlChar *name);
    

    用这个:

    typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name);
    

    第一个是函数声明,第二个是typedef(定义类型)。函数和类型是完全不同的东西。它们用于不同的目的:

    • 可以调用函数
    • 类型可用于制作变量,然后可以参与计算

    这就是你的编译器所说的“另一种符号”的意思——没有上下文(除非偶然)这些代码可以做任何类似的事情。例如,考虑一下代码片段 - 42&&。它们没有任何共同点——它们是两种不同的种类

    要了解声明的细节,这有点令人困惑,请使用right-left 规则,该规则也实现了here

    • typedef void (*xmlHashScanner)(whatever) 表示 xmlHashScanner 类型是一个指向函数的指针,该函数带有返回 void 的任何参数
    • void *xmlHashScanner(whatever) 表示 xmlHashScanner 是一个带有任何参数的函数,它返回 void *

    【讨论】:

      猜你喜欢
      • 2015-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多