2016-04-13 3 views
1

Пожалуйста, исправьте меня, где я понял неправильно.Почему для sqlite3_open мы используем двойной указатель **, а для sqlite3_prepare мы используем указатель *

Я прочитал этот ответ https://stackoverflow.com/a/833124/5175709, и я понял, что, поскольку объект может расширяться и заканчиваться из пространства, то ячейка памяти также меняет. Но здесь два синтаксиса sqlite3 ссылаются на объект по-разному. ЗАЧЕМ?

sqlite3_open мы имеем: sqlite3 **ppDb

SQLITE_API int SQLITE_STDCALL sqlite3_open(
    const char *filename, /* Database filename (UTF-8) */ 
    sqlite3 **ppDb   /* OUT: SQLite db handle */ 

И sqlite3_prepare мы имеем: sqlite3 *db

SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2(
    sqlite3 *db,   /* Database handle */ 
    const char *zSql,  /* SQL statement, UTF-8 encoded */ 
    int nByte,    /* Maximum length of zSql in bytes. */ 
    sqlite3_stmt **ppStmt, /* OUT: Statement handle */ 
    const char **pzTail  /* OUT: Pointer to unused portion of zSql */ 

ответ

2

sqlite3_open потребности каким-то образом дать вам объект подключения к базе данных; т.е. объект sqlite3.

Чтобы избежать доступа людей к внутренним частям, sqlite3.h объявляет sqlite3 непрозрачной структурой. Это означает, что вы не можете выделить место для sqlite3, так как вы не знаете, что он держит; библиотека SQLite должна выделить ее для вас и дать вам указатель на нее (sqlite3*).

Итак, теперь у нас есть гипотетическая функция sqlite3* sqlite3_open(...);, которая открывает БД и возвращает указатель на объект соединения. Но держитесь; что, если возникает ошибка? Мы могли бы вернуть NULL, но как разработчик должен различать ошибку «база данных не существует» из «базы данных только для чтения», «база данных повреждена» или других ошибок?

Таким образом, вместо этого sqlite3_open возвращает целочисленный код возврата и записывает указатель соединения в память, на который указывает параметр ppDB, если открытие выполнено успешно.

sqlite3_open обычно используется следующим образом:

sqlite3* myDB; 
int status = sqlite3_open("/path/to/db", &myDB); 
if(status != SQLITE_OK) { 
    // error occured 
    return; 
} 
// sqlite3_open wrote a database pointer to myDB, use it here 
status = sqlite3_prepare_v2(myDB, "SELECT * FROM whatever", -1, NULL, NULL); 
// ... 
+0

Отличный ответ C32, спасибо. Итак, вы говорите, что единственная причина, по которой мы это делаем, - это защита? Итак, если есть ошибка, sqlite3 * будет указывать на «nil»? А как насчет расширения памяти? Я все еще смущен этим. Не могли бы вы рассказать об этом? – Honey

+0

@ asma22 Единственный способ определить, произошла ли ошибка, - это посмотреть на возвращаемое значение; [SQLite все равно будет писать указатель базы данных, даже если он не может быть открыт] (http://sqlite.org/c3ref/open.html) (вероятно, чтобы вы могли получить от него сообщение об ошибке). Поскольку точная структура структуры sqlite3 скрыта от программы с использованием SQLite, SQLite может свободно добавлять или удалять из нее поля (что может изменить объем используемой памяти), не нарушая API или ABI. –

Смежные вопросы