Confused about accessing struct members via a pointer - c

I'm new to C, and am confused by results I'm getting when referencing a member of a struct via a pointer. See the following code for an example. What's happening when I reference tst->number the first time? What fundamental thing am I missing here?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int number;
} Test;
Test* Test_New(Test t,int number) {
t.number = number;
return &t;
}
int main(int argc, char** argv) {
Test test;
Test *tst = Test_New(test,10);
printf("Test.number = %d\n",tst->number);
printf("Test.number = %d\n",tst->number);
printf("Test.number = %d\n",tst->number);
}
The output is:
Test.number = 10
Test.number = 4206602
Test.number = 4206602

When you pass test into your Test_New function, you are passing it by value and so a local copy is made on the stack for the function scope of your Test_New function. Since you return the address of the variable, once the function returns the stack is useless but you've returned a pointer to a struct on the old stack! So you can see that your first call returns the correct value since nothing has overwritten your stack value but the subsequent calls (which all use the stack) overwrite your value and give you erroneous results.
To do this correctly rewrite your Test_New function to take a pointer and pass the pointer to the struct into the function.
Test* Test_New(Test * t,int number) {
t->number = number;
return t;
}
int main(int argc, char ** argv) {
Test test;
Test * tst = Test_New(&test,10);
printf("Test.number = %d\n",tst->number);
printf("Test.number = %d\n",tst->number);
printf("Test.number = %d\n",tst->number);
}

Independent of struct, it is always incorrect to return the address of a local variable. It is usually also incorrect to put the address of a local variable into a global variable or to store it in an object allocated on the heap with malloc. Generally if you need to return a pointer to an object, you'll need either to get someone else to provide the pointer for you, or else you'll need to allocate space with malloc, which will return a pointer. In that case, part of the API for your function must specify who is responsible for calling free when the object is no longer needed.

You are returning the address of t as declared in the method Test_New, not the address of test that you passed into the method. That is, test is being passed by value and you should instead pass a pointer to it.
So, here is what happens when you call Test_New. A new Test struct named t is created and t.number is set to be equal to the value of test.number (which you had not initialized). Then you set t.number equal to the parameter number that you passed to the method, and then you return the address of t. But t is a local variable and goes out of scope as soon as the method ends. Thus, you are returning a pointer to data that no longer exists and that is why you are ending up with garbage.
Change the declaration of Test_New to
Test* Test_New(Test* t,int number) {
t->number = number;
return t;
}
and call it via
Test *tst = Test_New(&test,10);
and all will go as you are expecting.

Just to extend BlodBath's answer, think about what happens in memory when you do this.
As you enter your main routine, a new automatic Test struct is created -- on the stack, since it's auto. So your stack looks something like
| return address for main | will be used at bottom
| argc | copied onto stack from environment
| argv address | copied onto stack from environment
-> | test.number | created by definition Test test;
with -> indicating the stack pointer to the last used element of the stack.
Now you call Test_new(), and it updates the stack like this:
| return address for main | will be used at bottom
| argc | copied onto stack from environment
| argv address | copied onto stack from environment
| test.number | created by definition Test test;
| return addr for Test_new| used to return at bottom
| copy of test.number | copied into the stack because C ALWAYS uses call by value
-> | 10 | copied onto stack
When you return &t, which address are you getting? Answer: the address of the data ON THE STACK. BUT THEN you return, the stack pointer is decremented. When you call printf, those words on the stack are re-used, but your address is still poiting to them. It happens that what the number in that location in the stack, interpreted as an address, points to has the value 4206602, but that's pure chance; in fact, it was kind of bad luck, as good luck would have been something that caused a segmentation fault, letting you know something was actually broken.

The problem is that you are not passing a reference into Test_New, you are passing a value. Then, you're returning the memory location of the local variable. Consider this code which demonstrates your problem:
#include <stdio.h>
typedef struct {
} Test;
void print_pass_by_value_memory(Test t) {
printf("%p\n", &t);
}
int main(int argc, char** argv) {
Test test;
printf("%p\n", &test);
print_pass_by_value_memory(test);
return 0;
}
The output of this program on my machine is:
0xbfffe970
0xbfffe950

Test t declared in Test_New() is a local variable. You are trying to return the address of a local variable. As the local variable gets destroyed once the function exists, the memory will be freed meaning, the compiler is free to put some other value in the location where your local variable was kept.
In your program when you are trying to access the value the second time, the memory location might have got assigned to a different variable or process. Hence you are getting the wrong output.
A better option for you will be to pass the structure from main() by reference rather than by value.

You've passed the contents of test by value to Test_New. IOW a new copy of a Test structure has been allocated on the stack when you called Test_New. It is the address of this Test that you return from the function.
When you use tst->number the first time the value of 10 is retrieved because although that stack has be unwound no other use of that memory has been made. However as soon as that first printf has been called the stack memory is reused for whatever it needs, but tst is still pointing to that memory. Hence subsquent uses of tst->number retrieve whatever printf left there in that memory.
Use Test &t in the function signature instead.

You could do something like this to make it a little easier:
typedef struct test {
int number;
} test_t;
test_t * Test_New(int num)
{
struct test *ptr;
ptr = (void *) malloc(sizeof(struct test));
if (! ptr) {
printf("Out of memory!\n");
return (void *) NULL;
}
ptr->number = num;
return ptr;
}
void cleanup(test_t *ptr)
{
if (ptr)
free(ptr);
}
....
int main(void)
{
test_t *test, *test1, *test2;
test = Test_New(10);
test1 = Test_New(20);
test2 = Test_new(30);
printf(
"Test (number) = %d\n"
"Test1 (number) = %d\n"
"Test2 (number) = %d\n",
test->number, test1->number, test2->number);
....
cleanup(test1);
cleanup(test2);
cleanup(test3);
return 0;
}
... As you can see, its easy to allocate room for several completely different instances of test_t, for instance if you need to save the existing state of one so you can revert later .. or for whatever reason.
Unless, of course there is some reason why you must keep it local .. but I really can't think of one.

Related

Pass by reference for pointers in C

I was trying to understand the concept of passing by reference. When I do this,
#include<stdio.h>
int recent (int *a)
{
*a = 20;
return 0;
}
int main()
{
int bee;
bee=5;
int *val = &bee;
printf("Value is %d\n", *val);
recent(val);
printf("Now Value is %d\n", *val);
return 0;
}
Basically I am making the pointer val point to the memory location of bee, and then when I pass it to recent function, and change the value, that change gets reflected in the calling function, so the value changes to 20. But when I do this,
#include<stdio.h>
int check = 20;
int recent (int *a)
{
a = &check;
return 0;
}
int main()
{
int bee;
bee=5;
int *val = NULL;
recent(val);
printf("Now Value is %d\n", *val);
return 0;
}
I get segmentation fault.
Is it because I didn't initialize the pointer to point to any location, and then I passed the value to recent function, and even though I made it point to a memory location (check variable), the calling function didnt catch that because I was passing by value?
Is this completely true or I misinterpreted something and got lucky with the answer?
Your problem is that you are printing the output of dereferencing the pointer val in the main function. The value of the pointer val in the main function is NULL. Thus the program is trying to print the thing at memory location 0, which is inaccessible to your program and results in a segmentation fault.
First you create the val pointer and assign it the value NULL.
int *val = NULL;
Then you call recent, passing it the pointer val, which still holds NULL.
recent(val);
Finally you print *val. val still holds NULL, and the * operator tells the compiler to "dereference" val, meaning to use the value of the thing that val is pointing to.
printf("Now Value is %d\n", *val);
In response to the question of whether your description is correct, the answer is sort of, but your description is imprecise. You made the function's copy of the pointer point to something. When you implement a pass-by-reference function in C using pointers, you are still passing the pointers themselves by value: a copy of the pointer is made, pushed onto the stack, and sent to the function. If you update the value of the pointer in the called function, the value of the pointer in the calling function will not be changed.
The reason has to do with your function recent(). When you pass in "a" you are passing in an int* (i.e. int pointer) which is an address to a location in memory. However, "a" as you have it, is local to this function (the pointer is pass by value).
Thus when you set "a = &check", you are only changing the local pointer value. As soon as recent() returns, "a" goes out of scope. In this context, you are never changing what "a" actually points to.
Thus, you segfault because val is still null, and you are trying to dereference a NULL pointer.
val is still a null pointer after leaving the function. The pointer itself is (as you correctly guessed) only passed by value, not by reference. Inside the function you are only modifying the pointer (which only lives insides the function), not the pointer target.
Besides that, please be careful with passing around memory locations to automatic stack variables. At least coming from a C++ background, it's considered bad style. Since you don't explicitly control the life cycle of a stack variable yourself (as you would do with malloc/free), you can easily shoot yourself in the foot by accidentally dereferencing pointers which have already been cleaned from the stack.
Is it because I didn't initialize the pointer to point to any location,
Code well initialized with int *val = NULL;, yet NULL is not a valid location. It isn't the NULL is a location or not. It is the NULL is the null pointer constant. As a null pointer, it "is guaranteed to compare unequal to a pointer to any object or function."
... and even though I made it point to a memory location (check variable), the calling function didn't catch that because I was passing by value?
Yes. With a = &check;, only the local a was affected, not the val in which a was copied from as the actual augment val was passed by value (copied) to the formal parameter a.
Is this completely true ...
IMO: Yes
... I misinterpreted something and got lucky with the answer?
It appears no misinterpretation. Lucky - hard to rate.
Here is what is going on in your code:
#include<stdio.h>
int check = 20;
int recent (int *a)
{
a = &check;
return 0;
}
int main()
{
// memory is allocated to hold an integer
int bee;
// the number 5 is written into that memory space
bee = 5;
// memory is allocated to hold a memory address
// the value of null (which is a invalid address) is written into it
int *val = NULL;
// more memory is allocated to hold a memory address (int* a)
// the address in val (which is null) is written into it
// the new memory address (a) now points to the address of check
recent(val);
// val is still NULL
// BOOOM!
printf("Now Value is %d\n", *val);
return 0;
}
Long story short, you are correct! :)
It's basically what all have answered. It's because you are passing the address pointed by pointer a using Pass By Value method. That is your sending in a copy of the address. If you want the second code to work you need to change the code to the following,
#include<stdio.h>
int check = 20;
int recent(int **a)
{
*a = &check;
return 0;
}
int main()
{
int bee;
bee = 5;
int *val = NULL;
recent(&val);
printf("Now Value is %d\n", *val);
return 0;
}
That is you have to Pass the address pointed by a by using C version of "Pass By Reference".

The logic behind pass by pointer to pointer in C

I learned from this page: FAQ that, if you want to initialize a pointer inside a function, then you should pass a pointer to pointer, i.e, **p as foo1()
void foo1(int **p) {
*p = malloc(100*sizeof(int)); // caller can get the memory
}
void foo2(int *p) {
p = malloc(100*sizeof(int)); // caller cannot get the memory
}
However, a pointer means its value is the address it points to. Where does the memory allocated in foo2() go after leaving its scope?
I still can't figure out the different behavior between passing pointer to value and pointer to pointer? I search through SO but only found the solution or short description. Could anyone help in more detail?
The memory allocated in foo2 is lost. This creates a memory leak because you have no idea where to find and use the allocated memory after foo2 returns.
Consider:
int *mymemory = NULL;
foo2(mymemory);
//mymemory is still NULL here. Memory has been allocated,
//but you don't know at which address
//in particular, you will never be able to free() it
versus:
int *mymemory = NULL;
foo1(&mymemory);
//mymemory is now the address of the memory
//allocated by the function
dostuffwith(mymemory);
free(mymemory);
Maybe it helps if we start with only one level of indirection.
consider this:
void foo1(int *p) {
^^
//this p is local to the foo1 function
//p contains the address of an int
*p = 12;
//now we dereference the pointer, so we set what p points to , to 12
}
void func(void) {
int x;
^^
//here is the x
foo1(&x);
^^
//now we find the location (address of) x, we copy that address
//into the arguments for foo1()
//foo1 sets our x int to 12
}
Let's add one more indiretion:
void foo1(int **p) {
^^
//this p is local to the foo1 function
//p contains the address of a pointer to an int
*p = NULL;
//now we dereferenced the pointer, so we get an int*. We just
//set it to NULL
}
void func(void) {
int *x;
^^
//here is the x.
foo1(&x);
^^
///now we find the location (address of) x, we copy that address
//into the arguments for foo1()
//foo1() sets the x pointer to NULL.
}
In both cases we are able to manipulate the x variable inside func1(), since the location(address of)
the x variable is passed into func1().
In the last case, we did *p = NULL;. Which would make x == NULL. We could have set it
to something that malloc() returned: *p = malloc(100)
But if we alter the first case:
void foo1(int *p) {
^^
//this p is local to the foo1 function
//p contains the address of an int
p = NULL;
//now we just set the local `p` variable to NULL.
//the caller will not see that, since `p` is just our own copy
//of pointer.
}
void func(void) {
int x;
^^
//here is the x
foo1(&x);
//foo1 just set its own copy of the pointer we created by doing `&x` to NULL.
//we will not see any changes here
}
We just set p = NULL; in the last case here. If we used malloc instead:
void foo1(int *p) {
^^
p = malloc(100);
//now we just set the local `p` variable to what malloc returns.
//the caller will not see that, since `p` is just our own local copy
//of the pointer.
//When foo1() returns, noone has any way of knowing the location
//of the memory buffer that malloc returned, so this memory is lost (a memory leak)
}
In your second example the memory allocated is leaked - once foo2 ends, there is no variable left that contains the address that was allocated, so it can't be freed.
You could also consider
void foo3 (int bar) {
bar = 8;
}
int main (int argc, char *argv[]) {
int x = 0;
foo3(x);
printf("%d\n", x);
return 0;
}
when foo3 ends, x is still 0 - the change to the contents of bar in foo3 don't affect the outer variable that was passed in. You're doing exactly the same when you pass in a single pointer - you're assigning the address of some memory to it, but then losing that address when the function exits.
To better understand indirection levels in C, it can be instructive to look at how the compiler organizes its memory.
Consider the following example :
void function1 (int var1, int var2) { ... }
In this case, function1 will receive 2 variables. But how ?
These variables will be put into the call stack memory. This is a linear, LIFO (Last in, First Out) type of allocation strategy.
Before calling function1(), the compiler will put var1 then var2 into the call stack, and increment the position of the call stack ceil. Then it will call function1(). function1() knows it must get 2 arguments, and so it finds them into the call stack.
What happens after function1() finishes ? Well, the call stack is decremented, and all variables into it are simply "disregarded", which is almost the same as "being erased".
So it's pretty clear that whatever you do to these variables during function1() is going to be lost for the calling program. If anything has to remain available to the calling program, it needs to be provided into a memory space that will survive the call stack decrement step.
Note that the logic is the same for any variable inside function1() : it will be unavailable to the calling function after function1() finishes. In essence, any result still stored into function1() memory space is "lost".
There are 2 ways to retrieve a usable result from a function.
The main one is to save the result of the function into a variable of the calling program/function. Consider this example :
int* foo3(size_t n) { return (int*) malloc(n); }
void callerFunction()
{
int* p;
p = foo3(100); // p is still available after foo3 exits
}
The second, more complex, one is to provide as an argument a pointer to a structure which exists into the calling memory space.
Consider this example :
typedef struct { int* p; } myStruct;
void foo4(myStruct* s) { s->p = (int*) malloc(100); }
void callerFunction()
{
myStruct s;
foo4(&s); //p is now available, inside s
}
It is more complex to read, but also more powerful. In this example, myStruct contains a single pointer, but the structure could be a lot more complex. This open the perspective to offer myriad of variables as the result of a function, instead of being limited to basic types, as for the previous example with foo3().
So what happens when you know that your structure is in fact a simple basic type ? Well, you can just provide a pointer to it. And, by the way, pointer is itself a basic type. So if you want to get the result of a modified pointer, you can provide as an argument, a pointer to a pointer. And there we find foo1().
void foo1(int **p) {
*p = (int *) malloc(100); // caller can get the memory
}
The problem with foo2 is that the p which is passed in is only modified inside the foo2 function. This is the same as :
void bar(int x)
{
x = 42;
}
...
int a = 7;
bar(a);
...
In the above code, a doesn't change because of the call to bar. Instead, a copy of a is passed to bar, and the copy is modified in bar.
The exact same thing happens in foo2. The memory is allocated, stored in p, which is a copy of the pointer passed in. When the code returns, the original pointer retains its original value.
By passing the address of a pointer (&ptr) to foo1, we can modify the ORIGINAL pointer, and thus pass the address of the allocation back to the caller of foo1.
Of course, when there is no reference back to the originally allocated memory, as is the case after a call to foo2, it is called a memory leak - generally considered a bad thing.
Passing a pointer to value: A copy of the pointer(i.e. address of the value) is made in the function(on the stack frame). This allows you to modify the value.
Passing a pointer to a pointer: A copy of the pointer to a pointer(i.e. address of the pointer which in turn points to the value) is made in the function(on the stack frame). This allows you to modify the value as well as the pointer to this value.
The memory allocated using malloc, calloc, realloc and new resided on the heap which means that it exists even after a function returns(stack frame destroyed).
void foo2(int *p) {
p = (int *) malloc(100); // caller cannot get the memory
}
However, since the pointer p is lost after the function is returned, this memory cannot be accessed and will result in a leak.
As behaviour of all arguments is the same as local variables (they are passed by value), you can not modify pointer passed by value.
So in foo2() you allocate memory, but you can not use it outside the function, as you actually modify local variable.
The foo() function actually modifies the value pointed by **p, so pointer passed to function will be updated.

Seg fault when using structure pointers to access struct members in C

What is wrong with my program, I get seg fault when I try to print the values.
My aim is assign some values in sample_function.
and in main function I want to copy the structure to another structure.
#include<stdio.h>
#include<string.h>
typedef struct
{
char *name;
char *class;
char *rollno;
} test;
test *
sample_function ()
{
test *abc;
abc = (test *)malloc(sizeof(test));
strcpy(abc->name,"Microsoft");
abc->class = "MD5";
abc->rollno = "12345";
printf("%s %s %s\n",abc->name,abc->class,abc->rollno);
return abc;
}
int main(){
test *digest_abc = NULL;
test *abc = NULL;
abc = sample_function();
digest_abc = abc;
printf(" %s %s %s \n",digest_abc->name,digest_abc->class,digest_abc->rollno);
return 1;
}
Pointer has always been a nightmare for me, I never understood it.
test * sample_function ()
{
test *abc;
strcpy(abc->name,"Surya");
What do you think abc points to, here? The answer is, it doesn't really point to anything. You need to initialize it to something, which in this case means allocating some memory.
So, let's fix that first issue:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
strcpy(abc->name,"Surya");
Now, abc points to something, and we can store stuff in there!
But ... abc->name is a pointer too, and what do you think that points to? Again, it doesn't really point to anything, and you certainly can't assume it points somewhere you can store your string.
So, let's fix your second issue:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
abc->name = strdup("Surya");
/* ... the rest is ok ... */
return abc;
}
Now, there's one last issue: you never release the memory you just allocated (this probably isn't an issue here, but it'd be a bug in a full-sized program).
So, at the end of main, you should have something like
free(abc->name);
free(abc);
return 1;
}
The final issue is a design one: you have three pointers in your structure, and only convention to help you remember which is dynamically allocated (and must be freed) and which point to string literals (and must not be freed).
That's fine, so long as this convention is followed everywhere. As soon as you dynamically allocate class or rollno, you have a memory leak. As soon as you point name at a string literal, you'll have a crash and/or heap damage.
As japreiss points out in a comment, a good way to enforce your convention is to write dedicated functions, like:
void initialize_test(test *obj, const char *name, char *class, char *rollno) {
obj->name = strdup(name);
...
}
void destroy_test(test *obj) {
free(obj->name);
}
test *malloc_test(const char *name, ...) {
test *obj = malloc(sizeof(*obj));
initialize_test(obj, name, ...);
return test;
}
void free_test(test *obj) {
destroy_test(obj);
free(obj);
}
In your function sample_function you return a pointer to abc. You cannot do this in C due to the way Activation Records are organized.
An Activation Record is a data structure that contains all the relevant information for a function call, parameters, return address, addresses of local variables, etc...
When you call a function a new Activation Record gets pushed onto the stack it could look something like this.
// Record for some function f(a, b)
| local variable 1 | <- stack pointer (abc in your case)
| local variable 2 |
| old stack pointer | <- base pointer
| return address |
| parameter 1 |
| parameter 2 |
---------------------
| caller activation |
| record |
When you return from a function this same activation record gets popped off of the stack but what happens if you returned the address of a variable that was on the old record ?
// popped record
| local variable 1 | <- address of abc #
| local variable 2 | #
| old stack pointer | # Unallocated memory, any new function
| return address | # call could overwrite this
| parameter 1 | #
| parameter 2 | #
--------------------- <- stack pointer
| caller activation |
| record |
Now you try to use abc and your program correctly crashes because it sees that you are accessing an area of memory that is unallocated.
You also have problems with allocation, but other answers have already covered that.
In sample_function you declare abc as a pointer to a test structure, but you never initialize it. It's just pointing off into the weeds somewhere. Then you try to dereference it to store values - BOOM.
Your program doesn't need any pointers at all; structures can be passed by value in C.
If you do want to keep similar interfaces to what you have now, you're going to have to add some dynamic allocations (malloc/free calls) to make sure your structures are actually allocated and that your pointers actually point to them.

Modifying struct members through a pointer passed to a function

for instance this code:
struct test{
int ID;
bool start;
};
struct test * sTest;
void changePointer(struct test * t)
{
t->ID = 3;
t->start = false;
}
int main(void)
{
sTest->ID = 5;
sTest->start = true;
changePointer(sTest);
return 0;
}
If I was to execute this code, then what would the output be? (i.e. if I pass a pointer like this, does it change the reference or is it just a copy?)
Thanks in advance!
Your program doesn't have any output, so there would be none.
It also never initializes the sTest pointer to point at some valid memory, so the results are totally undefined. This program invokes undefined behavior, and should/might/could crash when run.
IF the pointer had been initialized to point at a valid object of type struct test, the fields of that structure would have been changed so that at the end of main(), ID would be 3. The changes done inside changePointer() are done on the same memory as the changes done in main().
An easy fix would be:
int main(void)
{
struct test aTest;
sTest = &aTest; /* Notice the ampersand! */
sTest->start = true;
changePointer(sTest);
return 0;
}
Also note that C before C99 doesn't have a true keyword.
The only question is why do you need a test pointer in a global name space? Second is that you do not have any memory allocation operations. And you have a pointer as an input parameter of your function. Therefore structure where it points to will be changed in "changePointer".
1) First thing your code will crash since you are not allocating memory for saving structure.. you might need to add
sText = malloc(sizeof(struct test));
2) After correcting the crash, you can pass structure pointer and the changes you make in changePointer function will reflect in main and vizeversa..
3) But since you are not printing anything, there wont be any output to your program..

Need an explanation of how pointers work when passing in as function args

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.
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;
}
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;
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.
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"?.
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...

Resources