7

I have an array of void-Pointers and want to access the elements (inititialize them), but it do not work:

void* anyptr = ...; //a pointer to something
void* arr = (void*)malloc(sizeof(void*)*10);

int i=0;
for(i=0; i<10; i++)
   *(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too

I guess, the reason why this won´t work is that on the left side is the result of element i. But i don´t have an idea how to do this

0xDEADBEEF
  • 3,401
  • 8
  • 37
  • 66
  • 5
    Why do you cast `void *` to `void *`? [You should never cast it anyway.](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) –  Apr 20 '13 at 19:08
  • `*(arr+i)` void pointer dereferencing. – BLUEPIXY Apr 20 '13 at 19:10
  • 8
    Asking "why you do that?" to somebody who doesn't know what he/she is doing almost always sounds rude and not didactic. – Rafael Eyng Jun 03 '18 at 21:36

3 Answers3

27

There are two ways to initialize arrays in C:

  • On the stack (which will handle memory for you since it will be cleaned up when your function ends)
  • In the heap (which will require you to handle allocation and freeing on your own).

If you would like to use the stack, you could initialize your array like this...

#define ARRAY_LENGTH 10
void *ptr;
void *arr[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++) {
    arr[i] = ptr;
}

You can similarly define your array in the heap as follows...

#define ARRAY_LENGTH 10
void *ptr;
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH);
for (int i = 0; i < ARRAY_LENGTH; i++) {
    arr[i] = ptr;
}
free(arr);

It is important to remember that an array (besides arrays assigned in the stack, which have some additional attributes such as length) is essentially just a pointer to the first element, and the operation arr[i] is the same as moving i*sizeof(elem) bytes away from the first element, and accessing the memory there. If you would like to get a pointer to the ith index in the array, then you would use notations such as...

void *indexPtr = arr + i;

or

void *indexPtr = &( arr[i] );

In this fashion, an array of void*'s would be of type void **, since the variable is a pointer to the first member of the array, which is a pointer. This can be a bit confusing, but just always try to keep in mind what type the elements of the array are, and creating a pointer to them. So if the array is of type int, then the array would be of type int or int[], but if you are storing pointers to integers, you would initialize an array of type int * in either of these two forms...

int **arr = malloc(sizeof(int *) * ARRAY_LENGTH);
int *arr[ARRAY_LENGTH];

Also note that you are storing pointers, so if you run the code...

int *arr[4];
for (int i = 0; i < ARRAY_LENGTH; i++) {
    arr[i] = &i;
}

Although it may seem to be that the values pointed to in the array would be as follows- [0, 1, 2, 3], but in reality it would be [4, 4, 4, 4], since what you actually have is an array of pointers all pointing to the variable i in your function, so whenever you change that, the values pointed to in the array will all be changed.
I hope this helped

Joe Delgado
  • 308
  • 3
  • 6
12

You need to change this line

void* arr = (void*)malloc(sizeof(void*)*10);

to this

void** arr = malloc(sizeof(void*)*10);
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • Could you please explain why it is declared as a pointer to a pointer? – init Aug 06 '16 at 16:24
  • 3
    @init because that's what you're allocating memory for: 10 pointers. How do you point to this memory? You point to the first pointer. Hence, it's a pointer to a pointer. You add 1 to it and you point to the next pointer and so on until the last of the 10 pointers. – Alexey Frunze Aug 06 '16 at 22:02
3

You can't dereference a void pointer. That's the whole point of void pointers. Dereferencing a pointer provides you with access to the item that's found at the address the pointer points to. With a void pointer, however, you don't know how large the target object is (is it a 1B character or a 100B struct?). You have to cast it to a specific pointer type before dereferencing it.

Adding (or subtracting) an integer i to a pointer is then defined as adding i-times sizeof(*pointer) to the pointer's content. (You can only tell sizeof(*pointer) if your pointer has a specific type. Pointer arithmetic with void pointers makes no sense).

As for (arr+n)= anyptr;, arr+n is just an address. It's not a value you can assign something to (not an lvalue).

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • and how i can change the value on address arr+n? – 0xDEADBEEF Apr 20 '13 at 19:55
  • By casting it to a specific pointer type and then dereferencing it. Note, however, that ptr+n, if ptr is a non-void pointer will mean n items ahead of ptr, which doesn't necesserily mean n bytes (it does for char* pointers, but for int pointers it will most likely mean n*4 bytes ahead, and for pointers to pointers (of any type) it will mean 4*n or 8*n depending on your architecture (32 or 64 bit respectively). – Petr Skocik Apr 20 '13 at 20:05