1

I am trying to make a simple piece of c code using pointers work but memory is being overwritten unexpectedly.

I want to create an array of pointers to integers then create a pointer to an integer and assign it's address to an array.

Therefore, the array will point to a pointer to an integer. I did this in a function called add_value_to_array().

Here is my code :

void add_value_to_array(int *** array, int * value) {
    *array = &value;
}
int main() {

    int ** arr = { 0 };
    int value = 5;
    int * value_ptr =  &value;

    add_value_to_array(&arr, value_ptr);
    //arr = &value_ptr;
    printf("looool\n");
    printf("looool\n");
    printf("looool\n");
    printf("looool\n");
    printf("%p\n", arr[0]);

}

What I want is :

arr -> value_ptr -> 5
(arr = &value_ptr
*array = value_ptr
value_ptr = &value
*value_ptr = 5
**arr = 5)

however, this is what I have right after add_value_to_array() is called, but memory is overwritten when I call the printfs(), I get garbage values in my arr variable.

Even weirder, if I do directly arr = &value_ptr instead of calling add_value_to_array, things go as expected and memory is not overwritten by the printfs().

So it seems that memory is allocated differently if I use a function or if I do I do things outside of it.

What is happening that I am seeing this behavior?

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • 1
    Arrays are not dynamic in `c` (you cannot add/remove new items to 'builtin' arrays in `c`). You may check this also: https://stackoverflow.com/questions/3536153/c-dynamically-growing-array – Renat Jul 15 '19 at 09:08
  • 2
    `*array = &value;` is a recipe for fail. `value` is an automatic variable to that function. It doesn't exist after the function returns, and so goes its address into the ether. Saving that address for any reason is pretty-much a sign of something wrong before even running the program. – WhozCraig Jul 15 '19 at 09:10

2 Answers2

2

Following assumption: You want to create an array of length 1 (maybe greater length later) of pointers to int. And you want that single pointer in the array to point to the local variable named 'value'.

Then:

int* arr[] = { 0 }; // or { NULL }, if you prefer
//       ^  creates an array; either you specify size explicitly or it will be deduced
//          from initializer, as in this case

Arrays automatically decay to pointer to first element, if you pass them to a function. So:

add_value_to_array(arr, &value);
//                 ^ decays to pointer
//                        ^ here you still need a pointer; you can create it directly, though

Little problem left: arr decaying to pointer is of type int**. You need the same type in your function:

void add_value_to_array(int** array, int* value)
//                          ^ one asterisk less
{
    *array
//  ^ this one is NOW correct: array points to the first element of arr
//    dereferencing gives you exactly this element, i. e. the pointer

        = /* & */value;
//           ^ must be dropped: you already have a pointer and you assign it to
//             another one, which is fine.
}

Be aware that pointers simply are addresses of variables somewhere in memory. A bit simplified:

int n = 10;
int* p0 = &n;
int* p1 = &n; // p1 and p0 point both to the same variable n
int* p2 = p0; // now again p2 points to n
*p0 = 12;     // change the value pointed to
printf("%d\n", *p2); // will print 12, as both pointers point to the same address.

Function parameters do not differ in this respect, they are just ordinary variables. And it doesn't play a role if the pointee is a data value or a pointer itself:

int n = 10;
int m = 12;
int* p = &n;
int** p1 = &p; // pointer to pointer to int
int** p2 = p1; // both p1 and p2 point to p
*p1 = &m;      // re-assign the POINTER
printf("%d\n", **p2); // again prints 12:
                      // p1 and p2 both point to p which was reset to m, though...
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
0

Thank you all for your answers, this helped me find the bug : I had to pass my value_ptr by address and not by value.
Here is my corrected code :

void add_value_to_array(int *** array, int ** value_ptr) {
    *array = value_ptr;
}
int main() {

    int ** arr = { 0 };
    int value = 5;
    int * value_ptr =  &value;

    add_value_to_array(&arr, &value_ptr);
    //arr = &value_ptr;
    printf("looool\n");
    printf("looool\n");
    printf("looool\n");
    printf("looool\n");
    printf("%p\n", arr[0]);

}

Thank you all for your help !