我如何解释这个看似函数声明但不符合通常模式的声明?

Posted

技术标签:

【中文标题】我如何解释这个看似函数声明但不符合通常模式的声明?【英文标题】: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 之类的术语并没有真正找到任何地方。所以,如果这是一个骗局,我会很高兴它被关闭。

【问题讨论】:

【参考方案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;

【讨论】:

以上是关于我如何解释这个看似函数声明但不符合通常模式的声明?的主要内容,如果未能解决你的问题,请参考以下文章

C++ Visual Studio Windows:如何在 dll 中声明但不定义外部函数

如何匹配一个函数声明?

JS高级程序设计中对“私有作用域”的经典解释

用 C 语言向函数解释变量声明

Doctype 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?

如何解释复杂的 C/C++ 声明