0

I need to implement a variable length data array containing void pointers. And I ran into the problem that when trying to print from this array I always output the last element. Here is an abstract illustration of my problem and attempted implementation:

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

int main() {
    int capacity = 4; // for example

    void **array = malloc(capacity*sizeof(void*));
    // assign values to array elements
    for(int i = 0; i < capacity; i++) {
        array[i] = malloc(sizeof(void*)); // not sure if it necessary
        int a = i*i;
        array[i] = &a;
        printf("index: %d, element: %d\n", i, *(int*)array[i]); // for demonstration
    }
    printf("\n");
    /*
    * after that I try to print all the elements of the array sequentially
    */
    for(int i = 0; i < capacity; i++) {
        printf("index: %d, element: %d\n", i, *(int*)array[i]));
    }

    // I know that I do not free my memory, but that’s not the point
    return 0;
}

Output that i get looks like:

index: 0, element: 0
index: 1, element: 1
index: 2, element: 4
index: 3, element: 9

index: 0, element: 9
index: 1, element: 9
index: 2, element: 9
index: 3, element: 9

(Edit the questions: in the comments they pointed out to me that the error was in the way of putting the variable in the mass, because I did not take into account the lifetime of the variable in the for-loop and the principle of the pointer) How can I correctly fill a similar array without introducing a bunch of extra variables? Or the method that I chose is completely incorrect? I would be grateful for any help

4
  • 2
    array[i] = &a; stores pointers to a variable that's local to the loop - after the loop ends you have a lot of dangling pointers in your array Commented Dec 7, 2019 at 12:11
  • Please read more about scope and lifetime of variables. Commented Dec 7, 2019 at 12:17
  • Also think a little bit about what array[i] = ... followed by array[i] = ... really does. Commented Dec 7, 2019 at 12:17
  • Good. Thanks. This means that I misunderstood the essence of what my program displays and my error is not in output but putting the element in an array. How can I do it right? Save items to another array and then point to it? Commented Dec 7, 2019 at 12:27

2 Answers 2

1

You see the "last element", because a stays at the same position of the stack in each iteration, and thus &a stores that particular single address into all elements. Then the address contains the last value written there - until it becomes complete garbage when anything else overwrites it.

You would need different addresses, so you would need to allocate memory for each number, inside the loop. Which kind of happens already, just you allocate memory for a void*, while you would need an int, and you overwrite it, which (as the comments point out already) you simply should not do:

array[i] = malloc(sizeof(int));
*(int*)array[i] = i*i;
printf("index: %d, element: %d\n", i, *(int*)array[i]); // for demonstration

Then it works: https://ideone.com/dF4KY8 (an extra ) has been removed from the end)
Of course, you would need to free() stuff, as your own comment suggests.

Sign up to request clarification or add additional context in comments.

Comments

0

I hope, I can help you.

  1. malloc reserves space (as you probably already know) and returns a void*, not a void**. I would initialize it with:

    const int capacity = 4;
    int* array = (int*)malloc(capacity*sizeof(int)); 
    

I wouldn't initialize the array as void** because you plan to store many ints in it and an int array is nothing else than an int*. If you already initialize the array in the beginning you have not to call malloc again. 'malloc', returns the address, where the memory is allocated for you but you already know, where you want to store the data. If you have a void**, it is a multidimensional array. One thing left: On failure malloc returns a null-pointer a check whether the array is null, wouldn't harm you. :)

  1. There is a ')' too much within the printf();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.