Как я интерпретирую это объявление, которое кажется объявлением функции,но не соответствует обычной форме?
Я пытаюсь расшифровать это объявление из 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; }