2013-02-05 38 views
1

在功能混亂的sqlite3的結構在sqlite3的源代碼

static int sqlite3Prepare(
    sqlite3 *db,    /* Database handle. */ 
    const char *zSql,   /* UTF-8 encoded SQL statement. */ 
    int nBytes,    /* Length of zSql in bytes. */ 
    int saveSqlFlag,   /* True to copy SQL text into the sqlite3_stmt */ 
    Vdbe *pReprepare,   /* VM being reprepared */ 
    sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ 
    const char **pzTail  /* OUT: End of parsed string */ 
    ) { 
    ... 
    pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); 
    ... 
    assert(!db->mallocFailed); 
    ... 
} 

我知道sqlite3的只是一個假的結構中聲明爲

typedef struct sqlite3 sqlite3; 

沒有任何的身體。我知道sqlite3 *通常會投射到Vdbe*

但是,在這裏,dbsqlite3*的類型,db->malloFailed如何存在?爲什麼編譯器不抱怨?

有類似的情況sqlite3_stmt

typedef struct sqlite3_stmt sqlite3_stmt; 

沒有身體。我猜sqlite3_stmt是解析SQL語句的語法樹。我想看看它的結構。然而,這種類型使用這種奇怪的模式隱藏得如此之深,以至於我看不到它是什麼。

即使Vdbe也是同樣的情況......

typedef struct Vdbe Vdbe; 

在地球上是真正的struct

回答

4

sqlite3不是假結構; sqlite.h文件只是沒有定義它的正文。

它的定義是在sqliteInt.h文件(這也是sqlite3.c合併的一部分):

/* 
** Each database connection is an instance of the following structure. 
*/ 
struct sqlite3 { 
    sqlite3_vfs *pVfs;   /* OS Interface */ 
    struct Vdbe *pVdbe;   /* List of active virtual machines */ 
    CollSeq *pDfltColl;   /* The default collating sequence (BINARY) */ 
    ... 
    u8 mallocFailed;    /* True if we have seen a malloc failure */ 
    ... 
+0

你是完全正確的!真棒。所以一個「不透明的結構體」仍然有一個主體,只是在其他一些與它的聲明分開的文件中,但鏈接器會找到它,對嗎? –

+0

@AlfredZhong:是的 - 這就是opaque類型設計工作的方式。只要你不需要結構體的大小(你只有指向它們的指針),並且你不需要取消引用結構體的任何部分,你就不需要結構體。而使用命名'struct Something *'比使用'void *'好得多(更安全)。任何一個void指針都可以轉換爲任何其他(所以不匹配的錯誤不能被發現)。但是將'struct Something *'轉換爲'struct AnotherThing *'需要一個轉換,這使得錯誤成爲可能。 –