我如何解释这个似乎是函数声明的声明,但不适合通常的模具?

时间:2017-08-15 21:02:25

标签: c function declaration function-declaration

我正试图从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之类的字词实际上并不存在。所以,如果这是一个骗局,我会很高兴它被关闭。

2 个答案:

答案 0 :(得分:8)

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

函数和数组是需要进行体操解析的两个C类型类别。您可以将数组类型和函数类型视为“装饰”它们描述的标识符。如果你写(*),你就是说符号“foo”有一个整数类型。如果您编写int foo,则表示符号int foo(double)具有整数类型。 foo(double)foo必须粘在一起,因此任何进一步的装饰都必须将整个事物包裹起来,就好像它是一个单一的名字一样。

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

(double)

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

int ... (double)

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

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

答案 1 :(得分: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

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

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