#include<stdio.h>
int q = 10;
void fun(int *p){
*p = 15;
p = &q;
printf("%d ",*p);
}
int main(){
int r = 20;
int *p = &r;
fun(p);
printf("%d", *p);
return 0;
}
I was playing with pointers. Could not understand the output of this.
Output is coming as 10 15.
Once p is pointing to address of q, why on returning to main function it's value changes? Also why it changed to the value '15' which was assigned to it in the function before '10'.
Because p is fun() is not the same p in main(). p , in each function, is local. So changing one doesn't affect other.
In C, all function parameters are passed by value, including pointers.
*p = 15; will set r to 15 as *p is pointing to the memory occupied by r in main() prior to its reassignment to &q;
Your reassignment p = &q; does not change what p points to in the caller main(). To do that, you'd need to doubly indirect the pointer, i.e. change the function prototype to void fun(int **p){, call it using fun(&p);, and reassign using *p = &q;.
Two steps:
First call to fun(), assigning the address of global int q [holding value 10] to p inside the fucntion scope and printing it. The first output ==> 10;
Once the call returns from fun(), it will hold the previous address, [passed from main()] and hence, will print the value held by that address [which is 15, modified inside fun()].
Related
I was studying for a test with the following question with the given output :
#include <stdio.h>
int main()
{
int i = 10;
int *const p = &i;
foo(&p);
printf("%d\n", *p);
}
void foo(int **p)
{
int j = 11;
*p = &j;
printf("%d\n", **p);
}
Output : 11 11
I understand that the address of *p pointing to int i is passed to the function foo. Here, **p is a pointer pointing to *p, where *p points to int i.
In the function, **p pointer changes and points to int j, and the first printf is called and 11 is printed.
What I don't understand is the output from the 2nd printf function. Why is it printing 11, when it should be 10? I've checked and the value of int i and it did not change, so shouldn't dereferencing *p give 10 and not 11.
Can someone explain to me the logic behind what is happening and why is it happening?
First you asign p the address of i and you input the address of p to the function foo and inside the foo function the the value of p becomes what every the value in j (*p = &j). When the memory address changes in the foo function you are not changing it back.
NOTE: There the variable p is not passed by value, It is passed to the function by reference. So any change you do to the p variable inside the foo function will affect the p variable inside the main function because they have the same memory address
The line:
*p = &j;
makes the original variable
int *const p
point to the address of the local variable
int j
After foo is called, that local variable j has since been deallocated from the stack, but p is still pointing to that same stack location which still has that value of 11. So you are illegally accessing deallocated stack memory but it just happens to remain the value of 11. So it is printed a second time.
why the op is 20 ?? not 10 ? I think the op should be 10 but I don't know what happened? can you please explain it step by step
void fun(int *ptr)
{
int q=10;
ptr=&q;
}
int main()
{
int r=20;
int *p=&r;
fun(p);
printf("%d",*p);
return 0;
}
Values of function arguments are copies of what is passed from caller. Modifying in callee will not affect caller's local variables.
Non-static local variables will vanish on exiting its scope. Therefore, you must not dereference pointers to them after that.
To obtain 10, your code should be:
#include <stdio.h>
void fun(int **ptr) /* pass a pointer to modify caller's local variable */
{static int q=10; /* add static to prevent it from vanishing */
*ptr=&q; /* dereference the pointer */
}
int main()
{int r=20;
int *p=&r;
fun(&p); /* pass the pointer */
printf("%d",*p);
return 0;
}
This is p and r (addresses are for instance based)
---------------- ---------------- ----------------
| r 20 | | p 1234 | | q 10 |
---------------- ---------------- ----------------
^ ^ ^
|_ Address of r |_ Address of p |_ Address of q
= 1234 = 9876 = 12121
To fun(),
void fun(int *ptr) {
int q = 10;
ptr = &q;
}
you provide p as ptr (ie 1234), then set ptr to the address of q
fun: ptr = 12121
then fun ends, and ptr dies with it, the memory didn't change for r
To change something you have to pass the address of that thing. Even if it is a pointer.
Giving the address of p to fun
fun( &p );
and changing fun() to accept a pointer to pointer
void fun(int **ptr) { // <== pointer to pointer
int q = 10;
*ptr = &q; // <== change r indirectly
}
here, ptr has the address of the pointer p, ie 9876
*ptr = &q; // changes the value of `r`
It´s basically because of two reasons:
p in main() and ptr in fun() are two different pointers, and
You pass p by value, not by reference.
At the function call:
fun(p);
you just pass p by value; Means it passes the address of r (what is actually the value of p) to ptr.
With ptr = &q; in fun() you just assign the address of q to ptr, but not to p.
Therefore, the output of dereferencing p at:
printf("%d",*p);
is of course 20, as p still point to r -> the value of p didn´t changed.
If you instead pass p by reference and declare ptr as pointer to pointer (**), plus qualify q with static qualifier (because function-local automatic variables will be destroyed after the function is executed once):
void fun(int **ptr) // ptr is declared as pointer to pointer to int.
{
static int q = 10; // q is static -> It won´t get destroyed after returning from `fun()`.
*ptr = &q; // dereferencing ptr to assign the address of q to p.
}
int main()
{
int r = 20;
int *p = &r;
fun(&p); // Notice the `&` to gain the address of `p`, not `r`.
printf("%d",*p);
return 0;
}
The output would be 10 as we actually assigned the address of q to p.
As a side note: It is considered as bad programming style to refer to static-qualified function-local variables from a caller. I just showed this to you for the educational purpose and to show the difference to your provided code.
Try to assign an object pointed to in the caller, here f.e. r, by a passed pointer inside of the called function, here ptr, with the actual value of the object in the called function, here q.
This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 5 years ago.
I was trying out some pointer and function interaction and found out this behavior. The first printf prints 100 but the second printf prints 0!
Can somebody help me understand why?
void ptr_change (int **p)
{
int y = 100;
*p = &y;
}
int main ()
{
int x = 7;
int *p = &x;
ptr_change(&p);
printf("\nPtr = %d", *p);
printf("\nPtr = %d", *p);
return 0;
}
Compile:
gcc ptr2.c
Run and give output:
./a.out
Ptr = 100
Ptr = 0
y is an automatic local variable which will no longer exist after the function returns and you are assigning the address of an automatic local variable to the pointer.
In the main function you are dereferencing a pointer which no longer points to a valid location. This invokes undefined behavior. You can't expect anything good once there is undefined behavior of your code.
You return the address of an automatic variable from a procedure. The variable is no longer valid after the function returns. What happens next is called Undefined Behavior, however, an explanation for Intel machines and e.g. VC2008 is:
ptr_change(&p);
This places in p the address of the local variable y. After return from function ptr_change the stack space used by the function is released.
printf("\nPtr = %d", *p);
This first printf re-uses the stack space used earlier by ptr_change. It pushes 2 parameters onto the stack. The first parameter overwrites the stack space used by &p in your function call. y is not yet overwritten. The *p parameter of printf gets this value and pushes it onto the stack. The call to printf now overwrites int y.
printf("\nPtr = %d", *p);
As int y has been overwritten in the previous cal to printf, this call to printf prints garbage.
Note that any other form of undefined behavior is possible!
The value of y in
void ptr_change (int **p)
{
int y = 100;
*p = &y;
}
exists only temporary on stack as an automatic variable.
Once the function returns that location is not longer valid.
Compare the following program which passes pointer to the variable a and initializes pointer p.
#include<stdio.h>
void ptr_change2 (int **p, int *a)
{
*p = a;
}
int main ()
{
int x = 7;
int z = 8;
int *p = &x;
printf("\nPtr = %d", *p);
ptr_change2(&p,&z);
printf("\nPtr = %d", *p);
return 0;
}
Output:
Ptr = 7
Ptr = 8
*p = &y
is incorrect, you're assigning the address of y to the value of p.
try this instead:
p = &y
they will now have the same base address.
y = 100;
then print the pointer value of p
printf("%d", *p);
#include<stdio.h>
int i = 10;
void func(int *q){
q = &i;
}
int main(void){
int i = 20;
int *p = &i;
printf("%d\n",*p);
func(p);
printf("%d",*p);
return 0;
}
here value of p in 2nd printf statement should be 10... but when I execute it returns 20 how n why?
It would print 10 if you do this
*q = i
in the called function.
Change the content of that variable whose address is with you in the called function in the local variable q. Don't change the content of the local variable q.
You asked me why? Will explain...
This is what happened when you called the function and printed the value. Well this is not an exhaustive list but this points out the key things that will help in this context.
You got the address of the variable i in p.
Then you pass it to the called function.
Called function now has a local variable whose content is same as that of p.
Now you change the content of that local variable with the address of the global variable i.
Then function ends.
Rest in peace - local variable q. It is dead.
Then you again access *p in main() - meaning you looking for what value there is in the address contained in p.
you get 20.
Is there any other way to get 10?
Well there is
func(&p);
And then you do this
void func(int **q){
*q = &i;
}
Now you print *p you will get 10.
Know few things clearly, no matter what C is pass by value. Even here also q is a local variable. But now we have the address of p of main()
in q. So when you write *q=&i then you are basically going to the address of p from main() and then write there the address of global variable i. Then you come back. q is again lost. Then you print it - as you change to the original variable (p), the content there is 10.
Code-1
func(p);
then in func()
void func(int *q){
*q = i;
}
Code-2
func(&p);
then in func()
void func(int **q){
*q = &i;
}
Here
q = &i
You are setting the value of q, which is a local variable. Changing it does not change the value of the variable passed to func().
To have the 2nd call to printf() print 10, you want to write to where q is pointing.
*q = i;
q points to the inner i, which this way is set to 10.
here value of p in 2nd printf statement should be 10 (changed) ... but when I execute it returns 20 (same as original).
How and why?
q in void func(int *q) is a copy of p when func(p); is called.
void func(int *q){
q = &i;
}
int main(void){
...
func(p);
...
}
The change q = &i; inside void func(int *q) does not affect p in main().
I am trying to initialize the integer pointer "p" inside the "init_pointer" function. After the function returns I am printing the pointer and the dereferenced value twice. The first dereference prints the expected value 100, but the second dereference prints random values.
#include<stdio.h>
void init_pointer(int d, int **c){
(*c) = &d;
}
int main(){
int x = 100;
int *p;
init_pointer(x,&p);
printf("pointer = %p, value = %d\n",p,*p);
printf("pointer = %p, value = %d\n",p,*p);
return 0;
}
Output:
pointer = 0x7fffb4d4b9ac, value = 100
pointer = 0x7fffb4d4b9ac, value = 32567
The function has copied the value to a new local variable in init_pointer(int d, int **c)
d is local to init_pointer which was passed by main from x. Both x and d are separate variables whose addresses are different. Accessing the address of d outside init_pointer will lead to Undefined Behavior.
It would not make sense to call the function like this but this will work:
void init_pointer(int *d, int **c)
{
(*c) = d;
}
int main()
{
int x = 100;
int *p;
init_pointer(&x,&p);
printf("pointer = %p, value = %d\n",p,*p);
printf("pointer = %p, value = %d\n",p,*p);
return 0;
}
Output:
pointer = 0xbfde132c, value = 100
pointer = 0xbfde132c, value = 100
void init_pointer(int d, int **c){
(*c) = &d;
}
Here *c points to a local copy inside init_pointer(). Once init_pointer() returns, the address becomes invalid, and p in main() points to a freed address.
In init_pointer you assign the address of the parameter d to *c. The address of the parameter is a stack address.
In the first call to printf, the stack (although deallocated) is still intact, so p points to the discarded parameter d on the stack, which still has a value of 100, and *p is pushed first onto the stack.
In the second call to printf, the first call has overwritten the stack. Although the pointer still points to the same address, its value there has been overwritten by the push of p. Hence p (an address) is printed.
Notes: with "the stack (although deallocated)" I mean the stack of and below sp (intel; growing downward). Also, the stack can have been overwritten at any time, e.g. when interrupts occur.