Как я интерпретирую это объявление, которое кажется объявлением функции,но не соответствует обычной форме?
Я пытаюсь расшифровать это объявление из 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 ответа:
Это объявление функции, которая возвращает указатель на функцию. Тип возвращаемого значения:
void (*)(void)
(SQLITE_PRIVATE
расширяется доstatic
и не является частью возвращаемого типа, согласно комментариям), но имя функции (и параметры) должны появиться внутри части(*)
.Функции и массивы - это две категории типа C, которые требуют выполнения гимнастики для синтаксического анализа. Типы массивов и типы функций можно рассматривать как "украшение" идентификатора, который они описывают. Если вы пишете
Этот момент лучше всего иллюстрируется смешиванием типов массивов и типов функций, даже если конечный тип может быть нелегальным в C. (Это говорит о том, насколько нелеп синтаксис.) Например:int foo
, Вы говорите, что символ " foo " имеет целочисленный тип. Если вы пишетеint foo(double)
, вы говорите, что символfoo(double)
имеет целочисленный тип.foo
и(double)
должны держаться вместе, поэтому любое дальнейшее украшение должно обернуть всю вещь, как если бы это было одно имя.int foo[5](double)
Будет массивом (
foo[5]
) функций (int ... (double)
). С другой стороны:int foo(double)[5]
Является функцией (
foo(double)
) и возвращает массив (int ... [5]
).Внешний ресурс cdecl.org может помочь вам понять смысл такого рода заявлений. Однако вам нужно заменить имена структур стандартными типами (или написать типы структур как
struct sqlite_vfs
вместо простоsqlite_vfs
), чтобы он понял ваше объявление.
Это заявление
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, а затем без typedefFP f( void ); void ( *f( void) )( void ) { return h; }