1
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*
。
但是,在這裏,db
是sqlite3*
的類型,db->malloFailed
如何存在?爲什麼編譯器不抱怨?
有類似的情況sqlite3_stmt
:
typedef struct sqlite3_stmt sqlite3_stmt;
沒有身體。我猜sqlite3_stmt
是解析SQL語句的語法樹。我想看看它的結構。然而,這種類型使用這種奇怪的模式隱藏得如此之深,以至於我看不到它是什麼。
即使Vdbe
也是同樣的情況......
typedef struct Vdbe Vdbe;
在地球上是真正的struct
?
你是完全正確的!真棒。所以一個「不透明的結構體」仍然有一個主體,只是在其他一些與它的聲明分開的文件中,但鏈接器會找到它,對嗎? –
@AlfredZhong:是的 - 這就是opaque類型設計工作的方式。只要你不需要結構體的大小(你只有指向它們的指針),並且你不需要取消引用結構體的任何部分,你就不需要結構體。而使用命名'struct Something *'比使用'void *'好得多(更安全)。任何一個void指針都可以轉換爲任何其他(所以不匹配的錯誤不能被發現)。但是將'struct Something *'轉換爲'struct AnotherThing *'需要一個轉換,這使得錯誤成爲可能。 –