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.
Related
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.
#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().
#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()].
#include <stdio.h>
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
}
void foo(int **const p)
{
int j = 11;
*p = &j;
printf("%d ", **p);
}
What wii be the final output
Why Third printf will print undefined value ?
Within foo, you assign a value to *p which points to a location on the stack that's been allocated to foo. When foo returns, the stack is popped, and that location is free for reuse — but the p in main still points to it.
When you call printf in main the first time, it happens that that that location on the stack hasn't (yet) had any new data written to it, and so reading *p gives you 11, and you push that on the stack along with some other things for the call to printf, and it succeeds in printing 11. But the action of calling printf changes the data on the stack, including (potentially) the location that p (in main) points to, because the stack was popped after foo returned.
The second call then uses the data from that stack location again, which may have been changed by the first call to printf.
Moral of the story: Don't keep pointers to stack locations that have been popped.
the "i" in foo is stack-allocated, every thing will work fine until it goes off from the memory, so printf of foo will work fine,while the second printf and the third printf will work until the integer i of foo goes off from the memory. This is a system issue, it has the probability that the 2 last printf's work or don't work. If you wanna them work all the time you need to heap-allocate integer i of foo using mallo
Third printf is printing the right value. The problem is that j is an automatic local variable and it is no longer exist once function return. Therefore, p in main is not pointing to the place you are expecting and ultimately your program invokes undefined behaviour.
Possible solutions:
1. Use static keyword in the declaration of j
void foo(int **const p)
{
static int j = 11;
*p = &j;
printf("%d ", **p);
}
2. Dynamically allocate j
void foo(int **const p)
{
int *j = malloc(sizeof(int));
*j = 11;
*p = j;
printf("%d ", **p);
}
When void foo() is called ,new stack frame gets created on stack so int j = 11; being a local variable goes into this stack frame . So say int j is at address 0x000ffd with value 10 so your *p now stores this address . Now what happens when this function returns stack unwinds
During Stack Unwinding , it does all the work of cleanup. so all data which is into that stack frame gets destroyed so now that address 0x000ffd might have same value or something different but variable j is not associated to it now. So its undefined behavior
In my program, I am a passing a pointer to a function. In that function, I am making the passed pointer to point to a location what another pointer points. When returned from function it no longer points to its new location, instead it points to its original location. As I am passing by call by reference, it should point to its new location. Why is this happening?
// a program to show behavior of call by reference
#include <stdio.h>
#include <stdlib.h>
void ptrAllocation(int *p)
{
int k = 10 ;
int *t = &k;
p = t ;
printf("\np now points : %d",*p);
}
int main()
{
int i = 5 ;
int *a = &i;
ptrAllocation(a);
printf("\na now points : %d",*a);
}
Output:
p now points : 10
a now points : 5
I know the problem can be solved if I make a function like:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}
But I am not getting the clear picture of what is happening exactly in the program from the point of view of pointers, location, stack?
MY PROBLEM:
Is that the pointer k points to whatever pointer t points in the function ptrAllocation, but as the function returns, there no longer exists pointer t, hence pointer p points to its original location.
Is it not the case that when assigning a pointer to a pointer like in p = t, both pointers p and k point to the same location and not that p points to t and t points to the location.
Please describe how the stack and the pointers work in the program above.
You are passing by value, not by reference. What you pass by value is a pointer, but the pointer is still passed by value. You can change what it points at; you can't change the pointer in the calling function. If you wanted to do that, you'd have to pass a pointer to the pointer, as in your second code fragment.
Here's a derivative program based on your code, and its output from a 64-bit build on Mac OS X 10.8.3. I used 12 in the address printing to give uniform width pointer output on this machine; you can tune it to suit your machine.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
static int q = 42;
static void ptrAllocation(int *p, int **z)
{
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
int k = 10;
int *t = &k;
*z = &q;
p = t;
printf("After:\n");
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
}
int main(void)
{
int i = 5;
int j = 7;
int *a = &i;
int *b = &j;
printf("Before:\n");
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
ptrAllocation(a, &b);
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
}
Sample output:
Before:
a now points at: 5 (0x7FFF59E1852C)
b now points at: 7 (0x7FFF59E18530)
p now points at: 5 (0x7FFF59E1852C)
z now points at: 7 (0x7FFF59E18530) (0x7FFF59E18538)
After:
p now points at: 10 (0x7FFF59E18534)
z now points at: 42 (0x000105DE8050) (0x7FFF59E18538)
a now points at: 5 (0x7FFF59E1852C)
b now points at: 42 (0x000105DE8050)
Studying the output should help you understand better what is going on. You can print more address values if you need to.
Please describe how the stack and pointers work in the program above.
I'll discuss the program I showed because the addresses are available for discussion.
The variable q is located at address 0x000105DEE8050. Inside main(), variable i is stored on the stack at memory location 0x7FFF59E1852C; the variable j is stored at memory location 0x7FFF59E18530. The variable a contains the address of i; b contains the address of j; the address of b itself is 0x7FFF59E18538; the address of a is not shown in the output.
When ptrAllocation() is called, the value of a is pushed onto the stack, and the address of b is also pushed onto the stack. It is an implementation detail which order the values are pushed.
Inside ptrAllocation(), the variable p contains a copy of the value in a in the main() function. The variable z contains the address of b in the main() function. The variable k is on the stack; the variable t contains the address of k.
The assignment *z = &q; assigns the address of q to the pointer b via the argument z; it changes what b points at by changing the value of b in the calling function — which is only possible because the address of b was passed.
The assignment p = t; changes the local variable p (which contains a copy of what is in the variable a in main()) so that it points to what t points at, which is k. Therefore, the 'After' print statements note that p points at the value 10. The value that **z points at is in q and is still 42; *z is the address of q.
On return, a in the main() code is unchanged because its address was not passed to ptrAllocation(), but b is changed because its address was passed to ptrAllocation() and ptrAllocation() modified the pointer.
As noted in the comments to the question, your second implementation of ptrAllocation() is flawed too:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}
After calling this function, the pointer passed to it cannot reliably be dereferenced because *p points to a local variable which ceases to be valid once ptrAllocation() returns. You could fix this issue by making k into static int k = 10;, or by arranging for *p to point to some other int value that has a scope outside the function — a variable defined outside the function, or a dynamically allocated variable:
void ptrAllocation(int **p)
{
static int k = 10;
int *t = &k;
*p = t ;
printf("p now points : %d\n", **p);
}
Or:
void ptrAllocation(int **p)
{
*p = malloc(sizeof(*t));
if (*p != 0)
{
**p = 10;
printf("p now points : %d\n", **p);
}
}
Note, incidentally, how the code I've left has the newlines at the end of each printf() statement. Get into the habit of placing newlines at the end of lines of output. If you don't, you don't know when the output will appear (because it may be held up until the next time a newline is generated).
You are changing the pointer in function and not in the main code. Therefore only the copy will be changed. In the later case you change the location of pointer so the value at that address is changed. Take it like variables, when you change the copy, nothing happens to the original but when you change the location, the variable is changed. So you have to pass the address of pointer to change it.
The C language only implements call by value. Call by reference refers to passing (by value) a pointer p, and then using *p to manipulate what it points at (references).
If you want a function to change a pointer, you have to reference the pointer, such as by forming a pointer to pointer, and pass the reference to the function using call by value. The terms "reference" and "pointer" may be used nearly interchangeably in C — referencing is just what a pointer does.
In C++ call by reference is a language feature, but in C it's an idiom.