Pass by reference for pointers in C - 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".

Related

Returned array in C doesn't contain same values

I'm in the process of teaching myself C and I'm mistified as to what's causing the following issue: when I create an array in a method and return it as a pointer to the calling function, none of the content is correct. I've boiled down this problem to the following example:
char * makeArr(void){
char stuff[4];
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
printf("location of stuff:%p\n",stuff);
int i;
for(i = 0; i < 4; i++){
printf("%c\n",stuff[i]);
}
return stuff;
}
int main(void){
char* myarr;
myarr = makeArr();
int i;
printf("\n");
printf("location of myarr:%p\n", myarr);
for(i = 0; i < 4; i++){
printf("%c\n",myarr[i]);
}
}
The output returns the following:
location of stuff:0028FF08
a
b
c
d
location of myarr:0028FF08
Ä
ÿ
(
(a null character)
So I've verified that the locations between the two values are the same, however the values differ. I imagine that I'm missing some critical C caveat; I could speculate it's something to do with an array decaying into a pointer or a problem with the variable's scope, but and any light that could be shed on this would be much appreciated.
What you're attempting to do is return the address of a local variable, one that goes out of scope when the function exits, no different to:
char *fn(void) {
char xyzzy = '7';
return &xyzzy;
}
That's because, other than certain limited situations, an array will decay into a pointer to the first element of that array.
While you can technically return that pointer (it's not invalid in and of itself), what you can't do is dereference it afterwards with something like:
char *plugh = fn();
putchar (*plugh);
To do so is undefined behaviour, as per C11 6.5.3.2 Address and indirection operators /4 (my bold):
If an invalid value has been assigned to the pointer, the behaviour of the unary * operator is undefined.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
Having stated the problem, there are (at least) two ways to fix it.
First, you can create the array outside of the function (expanding its scope), and pass its address into the function to be populated.
void makeArr (char *stuff) {
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
}
int main(void) {
char myarr[4];
makeArr (myarr);
// Use myarr here
}
Second, you can dynamically allocate the array inside the function and pass it back. Items created on the heap do not go out of scope when a function exits, but you should both ensure that the allocation succeeded before trying to use it, and that you free the memory when you're finished with it.
char *makeArr (void) {
char *stuff = malloc (4);
if (stuff != NULL) {
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
}
return stuff;
}
int main(void) {
char *myarr;
myarr = makeArr();
if (myarr != NULL) {
// Use myarr here
free (myarr);
}
}
stuff[] only exists on the stack during function call, it gets written over after return. If you want it to hold values declare it static and it will do what you want.
However, the whole idea is fundamentally lame, don't do that in real life. If you want a function to initialize arrays, declare an array outside of the function, pass a pointer to this array as a parameter to the function and then initialize an array via that pointer. You may also want to pass the size of the array as a second parameter.
Since you're learning, a sample code is omitted intentionally.
Your array stuff is defined locally to the function makeArr. You should not expect it to survive past the life of that function.
char * makeArr(void){
char stuff[4];
Instead, try this:
char * makeArr(void){
char *stuff=(char*)calloc(4, sizeof(char));
This dynamically creates an array which will survive until you free() it.

Correct way to free memory in C

so I'm trying to understand the whole concept of memory management in C and I was given this code:
int main(int argc, int *argv[]) {
item *x = NULL;
x = (item *) malloc (sizeof(item));
...
free_item(&x);
}
void free_item(item **x) {
free(*x);
*x = NULL;
}
where item is earlier defined structure. The point, where I get confused is free_item(&x); because when I write free_item(x); and change the function to:
void free_item(item *x) {
free(x);
x = NULL;
}
the code seems to work the same way as the previous one.
So, is there any difference? And if not, is there any reason, why would someone send an adress on a pointer of a structure to a function, which frees this structure?
Yes. First, I think there's a typo in your modified function. It should be:
void free_item(item *x) {
free(x);
x = NULL;
}
Now, for the differences. The free call will succeed, as all it expects is a "pointer-to-type" variable for data which is allocated dynamically on the heap.
The second part, x = NULL, will not work as expected. Remember, in C, when passing an argument to a function, we pass by value always, never by reference. You are being passed a copy of a variable, so x = NULL just sets a temporarily automatically allocated copy of x to NULL, not the actual variable passed as an argument.
The original function which you changed does both parts correctly.
In the first case, to modify the content of pointer variable x, you need to pass on using a reference. That's why the &x and the double pointer is being used to free() the memeory which has been allocated from main(). This is correct.
in second case, a function-local copy of x will be created and passed on to free_item() which will have no impact on the x present in main(). The x = NULL; will have the scope only inside free_item().
In your first example you are calling free_item with argument of type pointer to pointer to item (assuming item **x argument).
In second example point value (main::x) is copied to free_item::x (different scope) and that copied value is set to NULL (and value is discarded afterwards).
Add printf("%p\n", x); to the end of main() (after free_item).
With first example you will see NULL and with second x will still be set to address previously stored there.
In first example, lets say your pointer is on address 0x00400000 and it points to memory allocated at 0x00410000.
0x00400000 0x00410000 <- x is stored here
0x00400004 0x00400000 <- tmp described later; point to x
...
0x00410000 .......... <- x points here; start of item - returned by malloc
When you call item **tmp = &x you will see that it will contain the address 0x00400000 (and tmp itself would be stored on different memory address).
Then in free_item():
free(*tmp); // The same as free(0x00410000)
*tmp = NULL; // Modifies data at 0x00400000 = NULL
When you use free ,you pass the pointer ,not the value of the pointer.
So, if you use
item *x
, you should use
free(x)
x = (item *) malloc (sizeof(item)); is unnecessary. x = malloc(sizeof(item)); will suffice.
2.
void free_item(item *data){
free(data);
}
Is the correct way to do it.
Write idiomatic C code. There is no difference perse but its hard do debug and maintain.
I would write free_item(x); rather than free_item(&x) and have free_item(item **x)

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.

pointer and which is pointed by the pointer

Update : Sorry, just a big mistake. It is meaningless to write int *a = 3; But please just think the analogy to the case like TCHAR *a = TEXT("text"); (I edited my question, so some answers and comments are strange, since they are for my original question which is not suitable)
In main function, suppose I have a pointer TCHAR *a = TEXT("text"); Then it excutes the following code:
int i;
for (i = 0; i < 1000; i++) {
a = test(i);
}
with the function TCHAR* test(int par) defined by:
TCHAR* test(int par)
{
TCHAR *b = TEXT("aaa");
return b;
}
My question is, after executing the above code, but before the program ends, in the memory:
1. the pointer `a` remains?
2. The 1000 pointers `b` are deleted each time the function test(...) exits ?
3. But there are still 1000 memory blocks there?
In fact, my question is motivated from the following code, which shows a tooltip when mouse is over a tab item in a tab control with the style TCS_TOOLTIPS:
case WM_NOTIFY
if (lpnmhdr->code == TTN_GETDISPINFO) {
LPNMTTDISPINFO lpnmtdi;
lpnmtdi = (LPNMTTDISPINFO)lParam;
int tabIndex = (int) wParam; // wParam is the index of the tab item.
lpnmtdi->lpszText = SetTabToolTipText(panel->gWin.At(tabIndex));
break;
}
I am thinking if the memory usage increases each time it calls
SetTabToolTipText(panel->gWin.At(tabIndex)), which manipulates with TCHAR and TCHAR* and return a value of type LPTSTR.
Yes, the pointer a remains till we return from the main function
The variable b (a 4-byte pointer) is automatic. It is created each time we call test function. Once we return from it, the variable disappears (the pointer). Please note, the value to which b points isn't affected.
No. In most of the cases, I think, there will be only one block allocated during compilation time (most likely in the read-only memory) and the function will be returning the same pointer on every invocation.
If SetTabToolTipText allocates a string inside using some memory management facilities new/malloc or some os-specific, you should do an additional cleanup. Otherwise there'll be a memory leak.
If nothing like this happens inside (it's not mentioned in the documentation or comments etc), it's most likely returning the pointer to some internal buffer which you typically use as readonly. In this case, there should be no concerns about a memory consumption increase.
You dont allocate any memory so you don't have to worry about memory being freed. When your vaiables go out of scope they will be freed automatically. In this function
int test(int par)
{
int *b = par;
}
you don't have a return value even though the function says that is will return an int, so you should probably do so as in this line
for (i = 0; i < 1000; i++) {
a = test(i);
}
you assign to a the value that is returned by test(). Also
int* a = 3;
int* b = par;
are asking for trouble. You are assigning integer values to a pointer variable. You should probably rethink your above code.
Pointer should contain adress... so int* a = 3 is something meaningless... And in function you don't allocate memory for int (only for par variable, which then destroy when the function ends), you allocate memory for storing adress in int* b, this memory also free when the funciton ends.

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