C - modify the address of a pointer passed to a function - c

I don't understand why the modification of pointer address passed as parameter to a function isn't persisted outside of this function (the address of ptr doesn't change after this function is called):
void advance(int *ptr) {
ptr = ptr + 1
}
When I can inside this same function modify the value pointed by ptr: *ptr = *ptr + 1.
PS: I know that I can achieve what I want using a pointer to a pointer: **ptr.

This behaviour is because parameters to functions in C are always passed by value. What you are passing by value here is an address. When you modify ptr you are modifying a copy of the caller's value.
To modify the caller's value you need an extra level of indirection:
void advance(int **ptr) {
*ptr = *ptr + 1;
}

When you define the function void advance(int *ptr) it means that a pointer in the stack will be created, which pointer points to the same addres as the original pointer. To see the proof try printing the address of orig pointer (&orig) and the address of the parameter pointer (&param), and the "pointed to" addresses (orig,param). The pointer addresses will differ, but the pointed to addresses will be the same.
So we have two pointers that points to the same area, if you modify the param, it will point to the new area, but the orig value will not be changed, it points to the same area as before.
That's why you need a pointer to a pointer. If you use a pointer to a pointer (int **ppointer = &orig), you will have a pointer that directly points to the area where orig stores the "pointed to" address (to where the orig points currently). By changing the value of the *ppointer, you will directly change the value of the orig as well.

Because C is not call by reference, it is always call-by-value, even with references/pointers as arguments.
It is not like other languages, where it can differentiate between argument types.

You actually answered you own question ;)
the modification of pointer address passed as parameter to a function isnt persisted outside of this function
Inside the function you are managing a copy of your parameter.
You can modify the value pointed because you are explicitly asking for change at a specific address.

****** /---\
* 20 * ----> | 2 |
****** \---/
i 20-24
Here i is a pointer pointing to the memory location 20 which has a value 2 i.e. when the binary data in 20 + sizeof(int) - 1 is interpreted as a decimal number. Now, when you pass i to advance, which has an argument ptr, what really happens is
****** /---\ ******
* 20 * ----> | 2 | &lt---- * 20 *
****** \---/ ******
i 20-24 ptr
ptr = i; i.e. the value of i is set to the value of ptr, which are really addresses here, since i and ptr are pointers.
When you increment ptr it'll just make the pointer point to a different address and not change anything with respect to i since ptr is a copy and not i itself. However, if you change the value at ptr using the operator * i.e. as *ptr = 10; then the 2 above will change to 10 thereby change *i as well, which is also pointing to 20. Again notice that i's address or value is untouched, only the location to which it is pointing to underwent a change. Had there been 10 pointers pointing to the address 20, even then none of them get changed, but all their pointed-to value gets changed.

See the function:
void demonstrate(int num) {
num = num + 1; // type of num is int
} // destroys "num", because num's scope is only "demonstrate" function
In your function:
void advance(int *ptr) {
ptr = ptr + 1; // type of ptr is int* and ptr is incremented
} // destroys "ptr" for the similar reason
But you want a function that modifies an address (IN pointer). So the complete solution should be:
#include <stdio.h>
void advance(int **ptr) { //ptr is a pointer to a pointer
// so *ptr is the pointer that is pointed by ptr
*ptr = *ptr + 1; // incrementing the address IN the pointer pointed by ptr
} // destroys "ptr" for the reason above
int main() {
int x = 5;
// initially assign "ptrToChange"
int *ptrToChange = &x;
// "ptrToChange" now points to x
// passing address OF "ptrToChange" to "advance" function
advance(&ptrToChange);
// now "ptrToChange" does NOT point to x
return 0;
}

Related

Unable to dereference double pointer in c

The output of this code is 20 20 10. The first 20 is easy to understand. But I am unable to understand how function change1 and change2 are accessing the variable b.
#include<stdio.h>
int a = 5, b = 10;
void change1(int *p);
void change2(int **pp);
main( )
{
int x=20, *ptr=&x;
printf("%d ",*ptr);
change1(ptr);
printf("%d ",*ptr);
change2(&ptr);
printf("%d\n",*ptr);
}
void change1(int *p)
{
p = &a;
}
void change2(int **pp)
{
*pp = &b;
}
But I am unable to understand how function change1 and change2 are accessing the variable b.
There is a misunderstanding of what change1 does.
It changes where p points to but that change is local to the function. It does not change where ptr points to in main since the pointer is passed by value. change1 does not have any code that accesses the variable b. It's not clear to me whey you think it does.
In change2, you are changing where the pointer points to, to b. The change affects where ptr points to in main since you are passing the address of ptr to change2 and you are changing where that dereferenced pointer points to.
In change1, p is a pointer to int that is passed by value. Assigning a value to p in change1 therefore has no effect because p is local to change1. This is the reason for the 2nd 20.
In change2, pp is a pointer to a pointer to int. It too is passed by value, but this time dereferencing pp (*pp) gives access to the location of the pointer (ptr), and it is into this location that the address of b (&b) is stored.
void change1(int *p)
{
p = &a;
}
The variable p is assigned with the address of a, but this is only valid within the function. p acts as a local variable within the function change1. After this function terminates, the pointer ptr would still be pointing at x(=20). This is the reason behind the second 20.
void change2(int **pp)
{
*pp = &b;
}
But this, is one of the correct ways to make changes to a pointer variable within the function so that it would still be valid outside. pp acts as a pointer pointing to the original ptr variable. As a result, ptr will end up pointing at b(=10) after change 2 terminates. This is the reason behind your third 10.
When you invoke change1() function, you're passing the pointer ptr as an argument. Let's suppose ptr = 0xcafebabe, and obviously *ptr = 20. Under the hood, you're writing the value 0xcafebabe on the stack, and the change1() function will only overwrite this value with &a on the stack frame corresponding to this function.
In the second case, you're passing a pointer to ptr as an argument. Let's suppose this pointer new_ptr has a value of 0xdeadbeef. In this case, *new_ptr = 0xcafebabe and you overwrite 0xcafebabe with &b (hence you are changing where the pointer is pointing.

Passing address, but it is working like call by value in C?

Hello I am a beginner in C programming language. Recently I read about call by value and call by address. I have learned that in call by address changes in the called functions reflects the callee. However the following code does not work like that.
int x = 10,y = 20;
void change_by_add(int *ptr) {
ptr = &y;
printf("\n Inside change_by_add\t %d",*ptr);
// here *ptr is printing 20
}
void main(){
int *p;
p = &x;
change_by_add(p);
printf("\nInside main\t %d", *p);
// here *p is still pointing to address of x and printing 10
}
When I am passing address then why the changes made by called function does not reflect caller?
The function is assigning a new address to the pointer but the pointer itself is being passed by value, as all arguments are in C. To change the value of a pointer variable the address of the pointer itself must be passed:
void change_by_add(int **ptr)
{
*ptr = &y;
}
change_by_add(&p);
See C FAQ Question 4.8.
Passing by reference does not exist in C but can be achieved by passing the address of the variable who's value is to be changed to a function. For example:
void add_to_int(int* a_value, int a_increment)
{
*a_value += a_increment;
}
You are simply setting the value of the pointer in the function, not the value of the pointed to variable. The function should use the following code:
*ptr = y;
This derefences the pointer (exposing the value pointed to), and therefore when you use the equals operator, the memory pointed at is modified, not the pointer itself. I hope this helps to clarify things.
Changes made by called function does not get reflected by the caller because you are overriding the pointer address in the called function i.e ptr = &y;.
Initially, you passed the address of x but you are changing it with the address of y.
If you really want to implement the concept of call by address then change value instead of address.
Example:
void change_by_add(int *ptr) {
*ptr = y; //changing value
printf("\nInside change_by_add\t %d",*ptr);
}
void main(){
int *p;
p = &x;
change_by_add(p);
printf("\nInside main\t %d \n", *p);
return 0;
}
Output
Inside change_by_add 20
Inside main 20
There is no such thing as call by address in C. There is only call by value. What one does when a function needs to modify an argument in a way that is visible to the caller is to have the caller pass a pointer to something, and have the called function write the update though that pointer. Note that the pointer itself is still sent as call-by-value - that is: the called function gets its own copy of the pointer and could change it to point to anything else if it wants to.

c - Access violation when reading array

I am trying to read an array of data and receiving an access violation. I can read the data from the array within the function that the array was allocated using:
AllCurrentData[newLineCount].data[tabCount] = malloc(length + 1);
strcpy( AllCurrentData[newLineCount].data[tabCount], buffer );
printf("%s", AllCurrentData[newLineCount].data[tabCount]);
But can't read it outside of the function. This is where I get the access violation, looks like it is trying to read a null location.
How can I access the data in the array AllCurrentData in a different function? thanks!
Extra info:
typedef struct current{
char **data;
}CurrentData;
AllCurrentData is declared in main:
CurrentData *AllCurrentData = '\0';
Function call
getCurrentData(current, AllCurrentData);
printf("%s", AllCurrentData[0].data[0]); //<----- error here
CurrentData *AllCurrentData = '\0';
This declares a pointer. This pointer is a variables that holds a number that is interpreted as an address. You initialize the pointer to '\0' (null).
getCurrentData(current, AllCurrentData);
Here you pass this pointer as parameter to function getCurrentData. As a pointer is a variable, this variable is passed by value, meaning that the function receives a copy of that value (the number that represents an address).
When inside the function if you write
AllCurrentData = malloc...
you modify that copy of the pointer, so outside the function AllCurrentData will still be '\0'.
You need to pass a pointer to that pointer (Inception, I know).
getCurrentData(current, &AllCurrentData);
getCurrentData(.., CurrentData **p_AllCurrentData) {
*p_AllCurrentData = malloc(...);
}
Let me explain this concept on a simpler example:
int *v = NULL; // here v is a pointer. This pointer has value 0 (invalid address)
v = malloc(10 * sizeof(int)); // here the pointer is assigned a valid address, lets say 0x41A0
f(v);
void f(int *x) {
// here the pointer x receives a copy of the value of the pointer v, so x will be, like v, 0x41A0
x[0] = 4;
/*this is ok as you modify the memory at the address 0x41A0,
so this modification is seen from outside the function, as v points to the same address.*/
x = malloc(...);
/* this is NOT ok, as x receives a new address, lets say 0xCC12.
But because x has a copy of the value from v, v will still be unmodified.*/
}
so if you want to allocate a pointer inside a function this is not ok:
int *v = NULL; // here v is a pointer. This pointer has value 0 (invalid address)
f(v);
void f(int *x) {
// here the pointer x receives a copy of the value of the pointer v, so x will be, like v, NULL
x = malloc(...);
/*this is NOT ok, as x receives a new address, lets say 0xCC12.
But because x has a copy of the value from v, v will still be unmodified,
it will still have NULL.*/
}
The right way to do is:
int *v = NULL; // here v is a pointer. This pointer has value 0 (invalid address)
// as v is a variable (of type pointer to int), v has an address, lets say 0xAAAA.
f(&v);
void f(int **p_x) {
/* here the p_x is a pointer to (a pointer of int),
so this pointer receives a copy of the value the address of p, so p_x is 0xAAAA.*/
*p_x = malloc(...);
/* lets say malloc returns the address 0xBBBB. This will be the address of our vector.
*p_x= says we modify the value at the address p_x. So the value found at the adress 0xAAAA
will be 0XBBBB. But because 0xAAAA is the address of v, we effectively modified the value of v
to 0xBBBB. So now v has the address of our starting vector.*/
// if you want to modify values inside this vector you need:
(*p_x)[0] = ...
}

double pointer vs single pointer

Can someone explain / give a reasoning to me on why the value of variable i in main function in below code snippet does not change via function test1 while it does change via test2? I think a single pointer should be sufficient to change the value of i. Why are we supposed to use double pointer?
#include <stdio.h>
void test1(int* pp)
{
int myVar = 9999;
pp = &myVar;
}
void test2(int** pp)
{
int myVar = 9999;
*pp = &myVar;
}
int main()
{
printf("Hej\n");
int i=1234;
int* p1;
p1 = &i;
test1(p1);
printf("does not change..., p1=%d\n",*p1);
test2(&p1);
printf("changes..., p1=%d\n",*p1);
return 0;
}
In C parameters are passed by value. This means that in test1 when you pass pp a copy is made of the pointer and when you change it the change is made to the copy not the pointer itself. With test2 the copy is of a double pointer but when you dereference and assign here
*pp = &myVar;
you are changing what is being pointed to, not changing pp itself. Take note that this behaviour in test2 is undefined as is documented in some of the other answers here
But you're not changing the value of i, you're changing the address that pp points to, if you only want to change the value of i then it's enough to change your test to:
void test3(int* pp)
{
int myVar = 9999;
*pp = myVar;
}
If you want to change the value of a variable of type T you have to use a pointer on that type (T*). Since you want to change a pointer (T = int*), you have to provide a pointer to a pointer (T* = int**), otherwise you're only going to change the copy.
Note that
int myVar = 9999;
*pp = &myVar;
will result in undefined behavior, since pp will now contain the address of a local variable which isn't valid after you exit the function.
Because f(x) can't change the value of x, no matter whether x is an int, a float, or a pointer.
void test1(int* pp)
{
int myVar = 9999;
pp = &myVar;
}
This function is passed a pointer pp. The function modifies that pointer. But since parameters are passed by value, that modification is not seen by the caller.
You need to write the function like this:
void test1(int* pp)
{
*pp = 9999;
}
The caller of this function is expected to pass the address of an int variable. The function then writes an int value, 9999 in this case, to that address. This is the key. You are passed an address, and you then write a value to that address. Your broken version simply modified the address. You were missing the indirection.
When the function returns, the caller can observe the modification to the int variable whose address was passed to the function. The calling code can look like this:
int i = 0;
test1(&i); // pass address of int variable
printf("%d\n", i); // prints the new value, 9999
void test2(int** pp)
{
int myVar = 9999;
*pp = &myVar;
}
Now, this is broken in a very serious way. This function does indeed return a pointer to the caller. But it returns a pointer to an object that goes out of scope as soon as the function returns. That is known as undefined behaviour. Don't do this. Never pass out of a function, a pointer to a local variable defined in that function.
pp = &myVar; assigns the address of myVar to the pointer pp. If you want to change the value that pp points to, use
*pp = myVar;
instead.
In answer to your second question, pass a pointer to a pointer when you want to change the object pointed to rather than changing the value of your existing object.
int* p1;
p1 = &i;
test1(p1); //1st
test2(&p1); //2nd
In simple way , 1st is pass by value and 2nd is pass by address.
Description :
In first case it passing pointer is actually the copy of that p inside test1 so the pp inside test1 is the local to that function and it's created in test1. You assigned the address and when comes out of function it's destroyed.
But in second case you are passing the address of the pointer to test2 function. So the pointer pp in test2 will point to the pointer p in main so assigning a new address to pp using *pp = &myVar will automatically set the value of p(since you are dereferencing the pointer). Hence when test2 terminates still p will point to modified location.

How are the pointed-to values of pointers being printed?

I found the following code in my textbook:
#include<stdio.h>
void disp( int *k)
{
printf("%d",*k);
}
int main( )
{
int i ;
int marks[ ] = { 55, 65, 75, 56, 78, 78, 90 } ;
for ( i = 0 ; i <= 6 ; i++ )
disp ( &marks[i] ) ;
return 0;
}
}
The code works just fine, but I have doubts regarding the logic:
I am sending the address of variables of the array. But in the disp function I am using a pointer variable as the argument and printing the value of the pointer. So the type of argument sent from the main function should mismatch with the argument of disp. So how does it work?
I tried to do the same by changing the disp function as
void disp( int (&k))
{
printf("%d",*k);
}
but I am getting an error. What should I do to make it work by taking an address as an argument, i.e. void disp(int &k)?
1) I am sending the address of variables of the array. But in the disp function I am using a pointer variable as argument and printing the value of the pointer.
Understand that a pointer is an address. So &marks[i] is an int*. And you're not printing the value of the pointer, but the value it points to.
printf("%d",*k);
the *k dereferences the pointer and gives the pointed-to value.
void disp( int (&k))
is invalid syntax in C, &k is not a valid identifier.
When you do: -
int *k = &marks[i];
The above statement is broken into: -
int *k; -> Integer Pointer
k = &marks[i]; --> `k` points to the address of marks[i]
So, basically, k is the an integer pointer, that points to the address of the current element in your array.
So, when you print *k, it is equivalent to: - *(&marks[i]), which dereferences the value and prints the element marks[i].
So, in the below code, you can understand, how the whole process of pointer assignment and de-referencing takes place: -
int *k; // Declaring integer pointer.
// Actually 'k' is equal to the `&marks[i]`.
// '*k' is just the indication of it being a pointer
k = &marks[i];
// Dereference pointer
*k = *(&marks[i]); --> = marks[i]
printf("%d",*k); --> printf("%d",marks[i]);
Also, since you cannot declare variable like: -
int &k = &marks[i];
You cannot have them as parameter in your function: -
void disp(int &k);
Because, eventually the address of array element passed is stored in this variable. So, it has to be int *k.
1) You understand correct that in the for loop the address is sent to disp. But disp receives pointer as an argument... which is just an address. Inside that function you don't print the "value" of the pointer. You print the value pointed by that pointer (the value that is on that address). In the printf call "*k" you dereference the pointer - get the value pointed by that pointer.
2) You didn't change the function so that it receives address. You changed it so that it receives reference. You can also say it receives a hidden pointer - it does the same as the pointer but you don't need to "*k" to dereference it - you use it as a normal variable
Read up on pointers and address-of variable. And how they're used.
When a function expects a pointer, you HAVE to send either a pointer or an address of a variable. Since pointers hold addresses.
The second problem you're facing is that of syntax error. Because there is no & operator that can be applied to "lvalues".
Well, simply i can say that you are passing an address in the function and recieving it in a pointer..Its correct as pointer can point to or hold the address. Or other way simply if you send an address but store it in a reference variable but the reference of whom, is the question to be asked. Try vice versa you'll understand the structure more better...

Resources