Reputation: 101
What I'm trying to do is store values in a array of Element struczs (that has a member void* data)
typedef struct {
void* data
} Element;
I have malloc'd the array to have 3 elements
Element* array = malloc(3 * sizeof(Element));
I know you can do it like this if data is a int but how do you do it if data is void *
array[0].data = 65;
I've tried typecasting
((*int)(array[0].data)) = 65;
but I get the message expected expression before 'int'
My second question is how would I go about storing a string in the Element struct (I can't make another member that is a string it has to be using the void pointer)
Can I use strcopy or sscanf ?
Sample main below in case I'm doing something wrong
#include "test.h"
int main (void)
{
Element* array = malloc(3 * sizeof(Element));
((*int)(array[0].data)) = 65;
((*int)(array[1].data)) = 64;
((*int)(array[2].data)) = 66;
}
EDIT
Sorry I should have added that the data will be added using a loop (the iterations is based on user input, so arrayOfElements could have 5,8,20 ect elements), based on user3386109 answer
Element* arrayOfElements = malloc(3 * sizeof(Element));
arrayOfElements[0].data = malloc( sizeof(int) );
int *ptr = arrayOfElements[0].data;
*ptr = 65;
work perfectly but if I want to make arrayOfElements[1].data = 67
Element* arrayOfElements = malloc(3 * sizeof(Element));
arrayOfElements[1].data = malloc( sizeof(int) );
int *ptr = arrayOfElements[1].data;
*ptr = 76;
I can't reuse *ptr even if I do free(ptr) , is there anyway to do this if you don't know how many elements arrayOfElements will have?
Upvotes: 2
Views: 2051
Reputation: 34829
The malloc
in your question creates an array of three structs. Each struct
has an uninitialized pointer called data
. Before you use that pointer you must initialize it with another call to malloc
.
To store an int
:
array[0].data = malloc( sizeof(int) );
int *ptr = array[0].data;
*ptr = 65;
To store a string:
array[0].data = malloc( strlen(str) + 1 );
strcpy( array[0].data, str );
Here's a complete example that shows how to initialize the array, print the elements of the array, and then free
the array. Note that ptr
is just a temporary variable that's used to avoid the nasty syntax associated with casting and dereferencing a void *
. (A good compiler will optimize out the ptr
variable.)
int main( void )
{
int *ptr;
char *str = "hello";
Element *array = malloc(3 * sizeof(Element) );
array[0].data = malloc( sizeof(int) );
ptr = array[0].data;
*ptr = 65;
array[1].data = malloc( strlen(str) + 1 );
strcpy( array[1].data, str );
array[2].data = malloc( sizeof(int) );
ptr = array[2].data;
*ptr = 76;
ptr = array[0].data;
printf( "%d\n", *ptr );
str = array[1].data;
printf( "%s\n", str );
ptr = array[2].data;
printf( "%d\n", *ptr );
for ( int i = 0; i < 3; i++ )
free( array[i].data );
free( array );
}
Upvotes: 4
Reputation: 148870
You are in a corner case here. C standard (draft n1256) specifies in 6.3 Conversions:
2 Conversion of an operand value to a compatible type causes no change to the value or the representation
And later in 6.3.2.3 Pointers:
5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.56)
6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.
The standard library defines even a special integer type intptr_t
that can accept without loss any pointer, but this is only an informative part.
Anyway, in all common implementations, it is safe to cast an integer to a pointer back and forth provided :
intptr_t
So you can do:
array[0].data = (void *) (intptr_t) 65;
and later
int i = (intptr_t) array[0].data;
Upvotes: 1