【问题标题】:How do I interpret this declaration that appears to be a function declaration, but doesn't fit the usual mould?我如何解释这个看似函数声明但不符合通常模式的声明?
【发布时间】:2018-01-23 21:13:57
【问题描述】:

我正在尝试从 sqlite3.c 中解读此声明

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);

好像是在声明一个函数,因为后面有这个

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
  return pVfs->xDlSym(pVfs, pHdle, zSym);
}

然后似乎是对函数的调用

xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);

xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);

但我无法理解声明。我强调了我无法理解的内容

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
                    ^                                                    ^^^^^^^

我想知道为什么声明不是这样

SQLITE_PRIVATE void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *);

我预计可能已经有人问过类似的问题,但搜索()void 之类的术语并没有真正找到任何地方。所以,如果这是一个骗局,我会很高兴它被关闭。

【问题讨论】:

    标签: c function declaration function-declaration


    【解决方案1】:

    这是声明一个返回函数指针的函数。返回类型为 void (*)(void)SQLITE_PRIVATE 扩展为 static,并且不是返回类型的一部分,每个 cmets),但函数名称(和参数)必须出现在 (*) 部分内。

    函数和数组是需要做体操才能解析的两个C类型类别。您可以将数组类型和函数类型视为“装饰”它们所描述的标识符。如果你写int foo,你是说符号“foo”有一个整数类型。如果你写int foo(double),你是说符号foo(double) 是一个整数类型。 foo(double) 必须粘在一起,所以任何进一步的装饰都必须将整个东西包裹起来,就好像它是一个名字一样。

    最好通过混合数组类型和函数类型来说明这一点,即使结束类型在 C 中可能不合法。(这说明了语法是多么荒谬。)例如:

    int foo[5](double)
    

    将是一个函数数组 (foo[5]) (int ... (double))。另一方面:

    int foo(double)[5]
    

    是一个函数 (foo(double)) 并返回一个数组 (int ... [5])。

    外部资源cdecl.org 可以帮助您理解这种声明。但是,您需要将结构名称替换为标准类型(或将结构类型写为struct sqlite_vfs 而不仅仅是sqlite_vfs)才能理解您的声明。

    【讨论】:

    • 谢谢,我尝试了 cdecl.org,但除了“语法错误”之外,它无法给我任何信息。我现在可以看到那是因为它无法识别sqlite3_vfs。如果我只是用int 替换sqlite3_vfs,那么我就会得到答案。
    • 我猜想的另一件事是虽然sqlite3OsDlSym返回“指向函数(void)返回void的指针”,但返回的实际函数指针具有不同的原型,因此(sqlite3_loadext_entry)演员。
    • 取决于 SQLITE_PRIVATE 的实际含义,它可能适用于被声明的函数而不是返回类型(例如,如果它是 static 的宏)
    • SQLITE_PRIVATE 扩展为 static 我相信
    【解决方案2】:

    此声明

    SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
    

    是一个函数的声明,其返回类型是该类型的函数指针

    void ( * )( void )
    

    可以通过引入 typedef 来简化声明。例如

    typedef void ( *FP )( void );
    
    SQLITE_PRIVATE  FP sqlite3OsDlSym(sqlite3_vfs *, void *, const char *);
    

    这是一个演示程序,它使用了一个返回指向另一个函数的指针的类似函数。

    #include <stdio.h>
    
    typedef void ( *FP )( void );
    
    void h( void )
    {
        puts( "Hello World" );
    }
    
    FP f( void );
    void ( *f( void) )( void )
    {
        return h;
    }
    
    int main(void) 
    {
        f()();
    
        return 0;
    }
    

    它的输出是

    Hello World
    

    首先函数f使用typedef声明,然后没有typedef

    FP f( void );
    void ( *f( void) )( void )
    {
        return h;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多