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).