How to pass pointer by reference in C?

I have the following code in C (not C++):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(){

    double *ptr=0;
    double x[3]={1,2,3};
    double y[2]={4,5};
    ptr=&x;
    for (int i=0; i<3; i++){
        printf("x: %f ", ptr[i]);
    }
    ptr=&y;
    for (int i=0; i<3; i++){
        printf("y: %f ", ptr[i]);
    }
    return 0;
}


This prints out 4 and 5 for ptr after reassigning it to y, as expected

But when I try passing it by reference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void changePtrRef(double **ptr);

int main(){

    double *ptr=0;
    double x[3]={1,2,3};
    double y[2]={4,5};
    ptr=&x;
    for (int i=0; i<3; i++){
        printf("x: %f ", ptr[i]);
    }
    //ptr=&y;
    changePtrRef(&ptr);

    for (int i=0; i<3; i++){
        printf("y: %f ", ptr[i]);
    }
    return 0;
}

void changePtrRef(double **ptr);
{
    double y[2]={14,15};
    *ptr=&y;
}


Then the values for x are printed out correctly, but the values for y are just garbage values that don't match 14 and 15 at all

Why is this?
1. Because the array at line 23 goes out of scope when the function returns. You have a pointer to junk. A quick hack is to make it a static array.

2. Your for loop at line 15 runs out of bounds, even if you fix 1.
Arrays are not pointers.
1
2
double x[3]={1,2,3};
double *ptr=&x; // incompatible type 

The name of the array x is convertible into a pointer to the first element of the array, with type double*. On the other hand, the expression &x computes the address of the array. It has the incompatible pointer-to-array type double(*)[3].

You need to say
double *ptr = x;
instead, and listen to your compiler's warnings.
Last edited on
Because the array at line 23 goes out of scope when the function returns. You have a pointer to junk. A quick hack is to make it a static array.


ok that works. Thanks

The name of the array x is convertible into a pointer to the first element of the array, with type double*. On the other hand, the expression &x computes the address of the array. It has the incompatible pointer-to-array type double(*)[3].


But the line ptr=&x; didn't seem to have problems as printf("x: %f ", ptr[i]); printed out the correct values. The problem was with changePtrRef(&ptr);
Last edited on
I have another problem that is related to the above in that it deals with pointers, but I wasn't sure if I should post a new topic or just write it here

I have C code in which I want to reassign a pointer on the stack with a pointer on the heap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int main(){

    double *ptrX=0;
    double *ptrY=0;
    double x[8]={0,0,0,0,0,0,0,0};
    double y[8]={0,0,0,0,0,0,0,0};
    ptrX=x;
    ptrY=y;

    double *Px1;    
    double *Py1;    
    Px1 = (double*)malloc(4*sizeof(double));
    Py1 = (double*)malloc(4*sizeof(double));
    Px1[0]=4.0; Px1[1]=0.0; Px1[2]=0.0; Px1[3]=0.0;
    Py1[0]=0.0; Py1[1]=0.0; Py1[2]=2.3; Py1[3]=2.3;
    ptrX=Px1;
    ptrY=Py1;

    for (int i=0; i<8; i++){
        printf("\n ptrX: %f ", ptrX[i]);
        printf("\t ptrY: %f ", ptrY[i]);
    }

    return 0;
}


The output will be

1
2
3
4
5
6
7
8
ptrX: 4.000000    ptrY: 0.000000
ptrX: 0.000000    ptrY: 0.000000
ptrX: 0.000000    ptrY: 2.300000
ptrX: 0.000000    ptrY: 2.300000
ptrX: 0.000000    ptrY: 0.000000
ptrX: -0.000000   ptrY: -0.000000
ptrX: 0.000000    ptrY: 0.000000
ptrX: 0.000000    ptrY: 0.000000


The first rows are what I expected. However, I thought garbage values should have been outputted for the for i=4 to 7 for ptrX and ptrY because I thought

1
2
ptrX=Px1;
ptrY=Py1;


made sure that ptrX and ptrY each pointed to arrays of length 4, so I thought it would erase the final 4 elements in ptrX and ptrY. How can I do this since the code above failed to do this?
> I thought garbage values should have been outputted for the for i=4 to 7 for ptrX and ptrY
Well they are garbage values.

But 'garbage' is very often zero.

There is no magic 'oh, this looks like a garbage value' which is guaranteed to appear whenever you step out of bounds.

made sure that ptrX and ptrY each pointed to arrays of length 4, so I thought it would erase the final 4 elements in ptrX and ptrY.

C and C++ will allow you to use array syntax to look at memory that is beyond the actual end of the array. So ptrX[7] gives the value held in memory at a location that's 7 array-elements-worth of memory after the start of the array. Even if you didn't allocate that memory to be part of the array in the first place.

How can I do this since the code above failed to do this?

You don't. You have no idea what that memory is being used for, so you absolutely don't want to be doing anything to try and change the contents of that memory.
Last edited on
is this what you need to see?

void getmem(int *&x)
{
delete[] x;
x = new int(100); //the pointer can be changed, it is reference.
}

ok new and delete are not C but the syntax for the function header should be ok and what you needed
Last edited on
@jonnin My C knowledge is very rusty, but I don't think C has references. So you'd need to pass a pointer to the pointer whose value the function will change.

1
2
3
4
5
void getmem(int **x)
{
delete[] *x;
*x = new int(100); //the pointer can be changed, it is reference.
}
But the line ptr=&x; didn't seem to have problems as printf("x: %f ", ptr[i]); printed out the correct values.
You're making the common mistake of thinking that code is correct because it prints the expected result. In truth your code works by accident. You'd be surprised (horrified?) to know just how much code in the world works by accident.

I thought garbage values should have been outputted for the for i=4 to 7 for ptrX and ptrY
There's no guarantee that the memory at ptrx[4] is even allocated to the process. The allocated memory for ptrX[3] might be at the end of a page and ptrX[4] might be at the beginning of a page that isn't allocated to the address space. So the program could just as easily crash with a SEGV as print nonsense (garbage) or zeros (also garbage).

This is why the language says that doing this provokes "undefined behavior" and that the behavior of the program from that point on is undefined. Basically, if you go out of bounds, there is no guarantee of any behavior whatsoever.
you are correct, C does not have references. The two languages are forever mangled in my head due to an early job I had where we compiled "C" code with a c++ compiler which of course meant it was really c++ code that was "mostly C". I have a bit of a mental block from that era. ** is the right answer.
Topic archived. No new replies allowed.