Никогда не определял структуру

Есть ли какое-либо преимущество в том, что никогда определило структуры в C?

Пример в исходном коде SQLite:

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

И как объект управляют так:

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


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

Итак, почему не только используют обычный абстрактный тип, с фактической структурой, конфиденциально определенной в foo.c источник и общественность typedef в foo.h заголовок?

12
задан Axel 19 July 2010 в 09:06
поделиться

2 ответа

Чтобы уточнить: вы спрашиваете, почему SQLite выполняет вышеупомянутое вместо этого:

Заголовочный файл:

typedef struct sqlite3_stmt sqlite3_stmt;

Файл C:

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


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

(Это каноническая форма шаблона «непрозрачный указатель», на который ссылается ответ Кенни.)

Единственная веская причина, по которой я могу думать о том, почему SQLite делает то, что он делает, заключается в следующем:

Я предполагаю, что внутренний код появился до API и использовал имя Vdbe - имя, вероятно, означает что-то, связанное с реализацией, например, «запись виртуальной базы данных» (здесь дико угадывается).

Когда пришло время создавать API, кто-то понял, что параметр, требуемый для sqlite3_step , был Vdbe , но это не совсем то имя, которое многое может передать пользователю. API. Следовательно, с точки зрения пользователя, Vdbe упоминается как sqlite3_stmt .

Таким образом, суть здесь состоит в том, чтобы различать два представления одного и того же элемента: серверная часть мыслит в терминах Vdbe s (какими бы они ни были), потому что это имя имеет смысл в контексте реализация .В API говорится о sqlite3_stmt s, потому что это имя имеет смысл в контексте интерфейса .

Править: Как указывает Амаргош, почему бы просто не сделать это для достижения того же эффекта?

typedef struct Vdbe sqlite3_stmt;

Кенни TM указывает на серьезную возможную причину (пожалуйста, проголосуйте за него, я не хочу откачивать его репутацию здесь): VDBE - только один из нескольких возможных бэкэндов; интерфейс использует «общий» sqlite3_stmt , который затем приводится к тому, что серверная часть использует для его реализации.

9
ответ дан 2 December 2019 в 06:25
поделиться

Это определено таким образом, чтобы скрыть детали реализации sqlite3_stmt от пользователя, тем самым избегая путаницы во внутренних состояниях. См. Непрозрачный указатель .

(Это также вынуждает пользователя использовать только тип в качестве указателя, поскольку сама структура sqlite3_stmt имеет неполную реализацию.)


Изменить: VDBE (виртуальный движок базы данных) просто "назад" -оконец API SQLite3. Я считаю, что серверная часть изменяема, поэтому sqlite3_stmt * не обязательно является Vdbe * . Не раскрывать Vdbe * в API, потому что внутренние детали не должны отображаться.

15
ответ дан 2 December 2019 в 06:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: