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