开发者

Never defined structure

Is there any benefit in having never-defined structures in C ?

Example in SQLite source code :

/* struct sqlite3_stmt is never defined */
typedef struct sqlite3_stmt sqlite3_stmt;

And the object is manipulated like so :

typedef struct Vdbe Vdbe;
struct Vdbe {
    /* lots of members */
};


int sqlite3_step(sqlite3_stmt *pStmt) {
    Vdbe *v = (Vdbe*) pStmt;
    /* do stuff with v... */
}

So why not just use a usual abstract type, with the actual st开发者_如何学编程ructure privately defined in foo.c source and a public typedef in foo.h header ?


It is defined like this to hide the implementation detail of sqlite3_stmt from the user, thus avoiding the internal states from being messed around. See Opaque pointer.

(This also forces the user only to use the type as a pointer since the structure sqlite3_stmt itself has incomplete implementation.)


Edit: VDBE (virtual database engine) is just "a" back-end of the SQLite3 API. I believe the back-end is changeable, thus a sqlite3_stmt* is not necessarily a Vdbe*. Not exposing Vdbe* in the API because the back-end detail should not be exposed.


To clarify: What you're asking is why SQLite does the above instead of doing this:

Header file:

typedef struct sqlite3_stmt sqlite3_stmt;

C file:

struct sqlite3_stmt {
    /* lots of members */
};


int sqlite3_step(sqlite3_stmt *pStmt) {
    /* do stuff with pStmt... */
}

(This is the canonical form of the "opaque pointer" pattern linked to in KennyTM's answer.)

The only good reason I can think of why SQLite does what it does is the following:

The backend code, I'm speculating, came before the API and used the name Vdbe -- the name probably means something related to the implementation along the lines of "virtual database entry" (guessing wildly here).

When time came to create the API, someone realized that the parameter required by sqlite3_step was a Vdbe but that this was not exactly a name that would convey a lot to the user of the API. Hence, from the user's point of view, a Vdbe is referred to as an sqlite3_stmt.

The point here, then, is to differentiate between two views of the same item: The backend thinks in terms of Vdbes (whatever they are) because that's a name that makes sense in the context of the implementation. The API talks about sqlite3_stmts because that's a name that makes sense in the context of the interface.

Edit: As Amarghosh points out, why not just do this to achieve the same effect?

typedef struct Vdbe sqlite3_stmt;

KennyTM points out a good possible reason (please vote him up, I don't want to siphon off his rep here): VDBE is only one of several possible backends; the interface uses a "generic" sqlite3_stmt, and this is then cast to whatever the backend uses to implement it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜