Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Pointer Assignment in a function

Why can't I assign a point in a function. As you noticed in the following code. I can not assign pointer p1 pointed to the correct address after the function return. But with the global pointer *p, I can store the address information.

#include <stdio.h>
#include <stdlib.h>

int *p = NULL;
void test(int * pt1, int**pt2){
    p = (int*)malloc(sizeof(int));    
    pt1 = p;
    *pt2 = p;
    printf("p points to %p\n", p);
    printf("pt1 points to %p\n", pt1);
    printf("pt2 points to %p\n", *pt2);
}

int main(void) {
    int *p1 = NULL; 
    int *p2 = NULL;

    printf("p points to %p\n", p);
    printf("p1 points to %p\n", p1);
    printf("p2 points to %p\n", p2);

    test(p1, &p2);

    printf("p points to %p\n", p);
    printf("p1 points to %p\n", p1);
    printf("p2 points to %p\n", p2);

    return 0;
}

OUTPUT:

p points to (nil)
p1 points to (nil)
p2 points to (nil)
p points to 0x8acb008
pt1 points to 0x8acb008
pt2 points to 0x8acb008
p points to 0x8acb008
p1 points to (nil)
p2 points to 0x8acb008
like image 731
user2052197 Avatar asked Feb 07 '13 20:02

user2052197


3 Answers

Inside test the variable pt1 is a discrete pointer in its own right. That is to say it is not merely an alias for p1, but rather a copy that exists only for the lifetime of the call.

Thus whatever assignment you make to it is only exits for the duration of that call and is not propagated outside of it. When you return from test the pointer pt1 ceases to exist and any changes aren't copied back.

As well as using an extra "layer" of pointer like you did with pt2 sometimes it's appropriate to use the return value to "share" changes with a wider audience:

#include <stdio.h>
#include <stdlib.h>

int *p = NULL;
int *test(int * pt1, int**pt2){
    p = (int*)malloc(sizeof(int));    
    pt1 = p;
    *pt2 = p;
    printf("p points to %p\n", p);
    printf("pt1 points to %p\n", pt1);
    printf("pt2 points to %p\n", *pt2);
    return pt1;
}

int main(void) {
    int *p1 = NULL; 
    int *p2 = NULL;

    printf("p points to %p\n", p);
    printf("p1 points to %p\n", p1);
    printf("p2 points to %p\n", p2);

    p1=test(p1, &p2);

    printf("p points to %p\n", p);
    printf("p1 points to %p\n", p1);
    printf("p2 points to %p\n", p2);

    return 0;
}
like image 57
Flexo Avatar answered Sep 25 '22 13:09

Flexo


You arre passing the p1 in by value, so the changes are only visable within the scope of that function. pass in a pointer to that pointer, as you did with p2, and you are fine.

#include <stdio.h>
#include <stdlib.h>

int *p = NULL;
void test(int **pt1, int**pt2){
    p = (int*)malloc(sizeof(int));    
    *pt1 = p;
    *pt2 = p;
    printf("p points to %p\n", p);
    printf("pt1 points to %p\n", pt1);
    printf("pt2 points to %p\n", *pt2);
}

int main(void) {
    int *p1 = NULL; 
    int *p2 = NULL;

    printf("p points to %p\n", p);
    printf("p1 points to %p\n", p1);
    printf("p2 points to %p\n", p2);

    test(&p1, &p2);

    printf("p points to %p\n", p);
    printf("p1 points to %p\n", p1);
    printf("p2 points to %p\n", p2);

    return 0;
}
like image 34
75inchpianist Avatar answered Sep 24 '22 13:09

75inchpianist


You're passing p1 by value, so it's not updated in the main function. However, you are passing p2 by reference (note that you wrote &p2), so it can be changed.

like image 31
William Avatar answered Sep 21 '22 13:09

William