Ответ 1
Чтобы уточнить: то, что вы спрашиваете, почему SQLite делает это выше, а не делает это:
Заголовочный файл:
typedef struct sqlite3_stmt sqlite3_stmt;
Файл C:
struct sqlite3_stmt {
/* lots of members */
};
int sqlite3_step(sqlite3_stmt *pStmt) {
/* do stuff with pStmt... */
}
(Это каноническая форма шаблона "непрозрачного указателя", связанная с ответом KennyTM.)
Единственная веская причина, по которой я могу думать о том, почему SQLite делает то, что она делает, выглядит следующим образом:
Бэкэнд-код, который я спекулировал, появился перед API и использовал имя Vdbe
- это имя, вероятно, означает что-то, связанное с реализацией в строках "виртуальной записи в базе данных" (угадывая дико здесь).
Когда пришло время создавать API, кто-то понял, что параметр, требуемый sqlite3_step
, был Vdbe
, но это было не совсем имя, которое могло бы передать пользователю API. Следовательно, с точки зрения пользователя a Vdbe
называется sqlite3_stmt
.
Таким образом, здесь следует различать два представления одного и того же элемента: Бэкэнд думает в терминах Vdbe
(независимо от того, что они есть), потому что это имя имеет смысл в контексте реализации. API говорит о sqlite3_stmt
, потому что это имя имеет смысл в контексте интерфейса.
Изменить: Как указывает Амархош, почему бы просто не сделать это для достижения того же эффекта?
typedef struct Vdbe sqlite3_stmt;
KennyTM указывает на хорошую возможную причину (пожалуйста, проголосуйте за него, я не хочу отключать его репутацию здесь): VDBE является лишь одним из нескольких возможных бэкэнды; интерфейс использует "общий" sqlite3_stmt
, и затем он применяется к тому, что использует бэкэнд для его реализации.