14

I have an array of arbitrary values, so I have defined it as an array of void pointers, so I can point to any kind of information (like int, character arrays, etc). However, how do I actually assign an int to it?

Take for example these initializations:

void* data[10];
int x = 100;

My intuition would think this, but this gives a compile error:

data[0] = malloc(sizeof(int));
*(data[0]) = x;

Also I thought about using &x, but I would take the address of a local variable, which (to my understanding) would be cleared after exiting from the procedure. So if I have a local variable x, how would I get it into a void pointer type of variable correctly?

sharptooth
  • 167,383
  • 100
  • 513
  • 979
pbean
  • 727
  • 1
  • 10
  • 20

5 Answers5

31
*((int*)data[0])=x;

will do it.

You might want to consider using a union. Something like this:

union myvalues
{
    int i;
    double d;
    long l;
};

You could then have

union myvalues *foo[10];
foo[0] = malloc(sizeof(union myvalues));
foo[0]->i = x;

You can also typedef the union. sizeof(union myvalues) will be the maximum of sizeof the members. So if you have int i; and char c[40] in the union, sizeof(union myvalues) will be 40. Writing to i will then overwrite the first 4 characters in c (assuming your ints are 4 bytes).

Jon Bright
  • 13,388
  • 3
  • 31
  • 46
  • Indeed, good point. I was going with the closest to the original. – Jon Bright Aug 25 '09 at 11:25
  • Thanks but would this work with character array pointers as well (char *). And would this not cause alignment issues on some platforms? And finally, if I have a char[40] it seems kind of a waste of memory to reserve 40 bytes if I'm only going to use 4. :-) – pbean Aug 25 '09 at 11:36
  • As I understand matters, unions are aligned at a boundary suitable for their largest member, so no alignment problems. char[40]: sure. This was just a handy example for explaining size. You could include a char* in the union. This might end up with two allocations (allocating the union, then the buffer pointed to by the char*). There would be two ways to avoid that: a) as Neil suggests above, just have an array of unions instead of an array of pointers to unions b) Do something like foo[0]=malloc(sizeof(union myvalues)+length_of_str+1); foo[0]->c=((char*)foo[0])+sizeof(union myvalues); – Jon Bright Aug 25 '09 at 12:45
  • Why do you need to deference it? doesn't the [] operator do that? (like if you have int *n; you just do n[0] = 23; not *(n[0]) = 23;) – Jonathan. Mar 03 '15 at 12:11
  • @Jonathan. the questioner had a void* data[10]; - i.e. an array of void*s. data[0] is therefore a void* and needs dereferencing. IOW, your example would be int **n, and you're doing n[0][0] = 23; or *(n[0])=23; – Jon Bright Mar 13 '15 at 10:54
11
*((int *)data[0]) = x;

A copy of x will be made, so the fact it is a local variable is not important.

4

for aliasing reasons its far better to do

mempcy( data[0], &x, sizeof( int ) );

As it happens the compiler will optimise the memcpy call out as sizeof( int ) is a constant value but it won't break various aliasing rules.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • I assume Goz is worried about type-punning, but since you can't dereference `void*`, it's always safe AFAIK to alias with a `void*` pointer. Just don't dereference it after casting to anything other than `int*` or `char*`. – Steve Jessop Aug 25 '09 at 12:35
2

Although you can use a cast to make the assignment, it is probably much cleaner to write the code like:

void *data[ 10 ];
int x = 100;
int *p;

p = malloc( sizeof *p );
data[ 0 ] = p;
*p = x;
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • I agree with you for this simple example, and that was the method I went for first. The problem however is that there are many different possible data types and such, so I would have to declare a lot of temporary local variables that might or might not be used at a certain execution. – pbean Aug 25 '09 at 12:20
1

try this:

data[0] = malloc(sizeof(int));
*((int*)data[0]) = x;

or

(int) (*(data[0])) = x;

don't forget to

free (data[0]);

afterwards.

frankster
  • 1,529
  • 2
  • 16
  • 20