tags:

views:

272

answers:

5

I thought I understood the basics of pointers, but after checking out some documentation on some sqlite3 methods I got thrown, so now I am unsure if my understanding is correct.

Here is a call to an sqlite3 method:

char* dataFilePath = "foobar.sqlite";
if (sqlite3_open(dataFilePath, &database) != SQLITE_OK) {...}

And here is the function header declaration:

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

Why is it that &database suddenly becomes a pointer to a pointer?

Another method call to close the database connection is: sqlite3_close(database);

With the following at the function header:

int sqlite3_close(sqlite3 *);

Why is this just a pointer, when I pass in a pointer? Would this not be a pointer to a pointer?

From all examples I have seen it always seemed the inverse of the functions above, ie.

// function
void foo(someDataType *bar) { ... }

// function call
foo(&bar);

Thanks for the help.

+15  A: 

Most likely, sqlite3_open is allocating memory for the database handle. For this reason the function needs a pointer to a pointer to the database handle (sqlite3) so that it can modify the pointer to the database handle. For example:

typedef struct { /*...*/ } sqlite3;

int sqlite3_open(const char *filename, sqlite3 **ppDb) {
    /* ... */

    // Allocate memory for the database handle.
    *ppDb = (sqlite3 *)malloc(sizeof(sqlite3));

    /* ... */
    return 0;
}

However, sqlite3_close only needs a single pointer to free the memory:

int sqlite3_close(sqlite3 *pDb) {
    /* ... Cleanup stuff ... */

    free(pDb);

    return 0;
}
Andrew Keeton
not likely, exactly that!
Nick D
chris
It's only incorrect if "var" is a value. If you already have a pointer, you can just pass it in as is.
Sean
@iso You're almost there. When a function has an argument that's a pointer, it wants a pointer. It doesn't matter how you get the pointer, though. So if you have a function `int func(int *ip)`, it wants a pointer to `int`. Whether you give it `int x = 5; func(` or `int *ix; *ix = 5; func(ix);` doesn't matter.
Andrew Keeton
@Andrew: That makes much more sense. Thanks
chris
+4  A: 

A pointer is the address of a variable.

Assuming that database is declared as sqlite3* database;, &database is the address of (or, a pointer to) the database pointer.

sqlite3_open takes a pointer to a pointer so that it can set the value that the pointer points to. It makes a sqlite value, and changes your pointer to point to it. sqlite3_close doesn't change what the pointer points to, so all it needs is the pointer itself.

SLaks
+5  A: 

I think the short explanation for what you're asking is that using "&" essentially means "a pointer to this"

int value = 0;
int *pointer = &value;
int **doublePointer = &pointer;
Sean
I didn't know that you could do what you did in the third line. Although I don't understand what exactly is happening on that one in regards to mem addresses, it does explain the sqlite3_open method.
chris
When "value" is declared, memory is set aside for that int.When "pointer" is declared, memory is set aside for the int* and it holds onto the address of "value".When "doublePointer" is declared, you're assigning the address of whatever memory was set aside for "pointer".
Sean
A: 

As usual, the C FAQ List contains relevant information. See I have a function which accepts, and is supposed to initialize, a pointer: and Does C even have "pass by reference"?.

Sinan Ünür
A: 

i don't know what you want to do with sqlite function. But using pointers makes you to keep changes in functions.

When you pass a variable to a function, the variable will be duplicated.

for example

int var1=0;
in *ptr1=&var1;
func(var1, ptr1);

the value of var1=5

the adress of var1 = 0xff2200 (something like that)

the value of ptr1 = 0xff2200 (the adress of var1)

the adress of ptr1 = 0xff0022 (something different)

Lets write a function which uses these two var as arg

void func1(int x, int *p){
    x+=5;
    (*p)-=5;
}

after u use this function;

func(var1, ptr1);

var1 will not equal to 0!!! İt will be -5

Because; in function func1

the value of x = 0 (the value of var1)

the adress of x = 0xaabbcc (something different then var1!!! this is why x+=5 is not effective on var1. It happens in another part of memory! When u return, this memory will be free again. And you'll lose your changes...)

the adress of p = 0xcccccc (something different too)

the value of p = 0xff2200 (the value of ptr1 and the adress of var1! This operation will be done in the var1's adress so you will not lose your changes)

İf we have to keep our changes of variables -in functions-, we have to use pointers for those var. İf our variable keep an adress, it means; it is a pointer. And if we want to keep changes of pointer -in functions- then we have to use pointer to pointer.

This is my first message and i hope this will be helpfull...

And "pass by reference" means "pass by pointer" other languages don't use pointers. so you have to pass by reference sometimes. But in C, pointers will do its job...

H2O