-2

Why in this code the pointer shifts to another location:

#include <stdio.h>

void f(int *p)
{
        int j=2;
        p=&j;
        printf("%d\n%p\n%d\n",*p,&j,p);
}

int main(void)
{
        int *q;
        int m=98;
        q=&m;
        f(q);
        printf("%p ",q);
        return 0;
}

Output:

2
0x7ffff5bf1bcc
0x7ffff5bf1bcc
0x7ffff5bf1bc8

I understand that when the function f() is done with printing value of j and address of j the memory occupied by j goes back to the stack but IMO p should continue pointing that location even after the function is over & it should be printing the same address in main as well. What is wrong with this?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Gaurav
  • 201
  • 1
  • 11

4 Answers4

6

Considering you meant printf("%p ", (void *)q); in the actual code,

No, function argument(s) in C is (are) passed by value. It won't reflect the changes made to the parameter into the actual arguments used (in function call) themselves.

To put it into other words, the function parameters are local to the function (call) scope, any changes made to them won't be reflected to the actual arguments.

So, if you need to change a pointer, you need to pass a pointer to the pointer which needs to be changed.

Consider a rather light-hearted but realistic scenario.

void f (int x) { x = 10; }

int main(void) { f(5); printf ("%d", 5); return 0;}

Now, do you expect it to print 10?


That said, an advice. Always cast the argument to %p conversion specifier to (void *) (if it is not already). printf() is a variadic function and for pointers, no default argument promotion happens, so the supplied argument type needs to match the expected type, explicitly. Otherwise, technically it is undefined behavior.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
2

Learn the difference between Pointers and Pointers to pointers - the pointer passed p is no doubt good to change the value of the variable it is pointing to (m), but to change the memory location it is pointing to - you need a pointer to pointer.

1

Expanding on top of what @SouravGhosh said, when you pass in a pointer to an int you are making a copy of the pointer. If you wanted to change the pointer you need to be doubly indirect and pass in a pointer to a pointer to an int. The first pointer is copied and you can directly affect the second pointer.

void f(int ** p)
{
    int j = 2;
    *p = &j;
    printf("%d\n%p\n%p\n",*p,&j,p); 
}

int main(void)
{
    int ** q = (int **)malloc( izeof(int *));
    int m = 98;
    *q = &m;
    f(q);
    printf("%p ",q);
    free(q);
    return 0;
}

And the output is

2 0xffffcbcc 0xffffcbcc 0xffffcbcc

jakedipity
  • 890
  • 8
  • 19
  • 2
    We might want to add that getting a pointer to a local variable in another function is less than useful. You can't do much with a dangling pointer. – Bo Persson Jul 25 '17 at 09:24
  • @BoPersson I'd say, it's __dangerous__. I don;t want to see my laptop on fire (_or, an automatic order of pizza for the whole staff in my office using my credit card_). – Sourav Ghosh Jul 25 '17 at 09:35
0

If you do this you'll see that it never changes:

#include <iostream>
#include "Header2.h"
#include "header1.h"

#include <stdio.h>
void f(int *p)
{
    int j = 2;
    p = &j;
    printf("%d\n%p\n%p\n", *p, &j, p);
}

int main(void)
{
    int *q;
    int m = 98;
    q = &m;
    printf("Value of pointer q before calling f() =%p ", q);
    f(q);
    printf("Value of pointer q after calling f() =%p ", q);
    return 0;
}
Zebrafish
  • 11,682
  • 3
  • 43
  • 119