2017-08-15 2 views
8

私は、その後の呼び出しのように見えるものをこの関数宣言のように見えるが、通常の型には適合しないこの宣言をどのように解釈すればよいですか?

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ 
    return pVfs->xDlSym(pVfs, pHdle, zSym); 
} 

、その後があるので、それは関数を宣言されたように思えsqlite3.c

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); 

からこの宣言を解読しようとしています機能

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 *); 

ようにされていませんなぜ私は思ったんだけど

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); 
        ^             ^^^^^^^ 

を理解することはできません何を強調してきました()voidは実際にはどこにもいません。だから、もしこれが欺瞞であれば、そのように閉じられるのはとても幸せです。

答えて

7

これは、関数ポインタを返す関数を宣言しています。戻り値の型はvoid (*)(void)(に展開され、コメントごとの戻り値の型ではありません)ですが、関数名(およびパラメータ)は(*)の部分に表示する必要があります。

機能と配列は、体操をして解析する必要がある2つのCタイプのカテゴリです。配列型と関数型は、それらが記述する識別子を「装飾」するものと考えることができます。 int fooと書くと、シンボル "foo"は整数型であると言われます。 int foo(double)と書くと、シンボルfoo(double)に整数型があるといえます。 foo(double)は一緒に固執しなければならないので、それ以上の装飾はすべてが単一の名前であるかのように全体を包む必要があります。

int foo[5](double) 

ポイントは最高のエンドタイプは例えば(。それは構文がどのようにばかげについて多くのことを言います)C.に法的ではないかもしれないにもかかわらず、配列型と関数型を混合することによって例示されています

は、関数(int ... (double))の配列(foo[5])になります。一方:

int foo(double)[5] 

関数(foo(double))とアレイ(int ... [5])を返します。

外部リソースcdecl.orgは、この種の宣言を理解するのに役立ちます。ただし、宣言を理解するには、構造体名を標準タイプ(またはsqlite_vfsではなくstruct sqlite_vfs)に置き換える必要があります。

+0

おかげで、私はcdecl.orgを試してみましたが、できませんでした"構文エラー"以外のものを私に与えるようにしてください。私はそれが 'sqlite3_vfs'を認識しなかったので、これを見ることができます。私が 'sqlite3_vfs'を' int'に置き換えたのであれば、私は答えがあったでしょう。 –

+0

また、 'sqlite3OsDlSym'は" void(void)return to void "ポインタを返しますが、返される実際の関数ポインタは異なるプロトタイプを持ち、したがって'(sqlite3_loadext_entry) 'キャストがあります。 –

+0

実際に '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; 
} 

その出力は、最初の関数f

Hello World 

では、typedefのを使用して宣言され、その後のtypedefせずに

FP f(void); 
void (*f(void))(void) 
{ 
    return h; 
} 
関連する問題