I have a dynamic array with this struct:
typedef struct vector_struct {
size_t e_sz;
char e_type;
#define V_INT 1
#define V_DOUBLE 2
#define V_CHAR 3
#define V_FLOAT 4
unsigned no_e;
unsigned cur_cap;
void* e_array;
}* vector_type;
where no_e is the size, cur_cap the capacity, e_sz is the size of the elements in the array and e_array is the void pointer.
I had to complete a push_back function that has to work for the 4 differetns types defined above.
void v_push_back(vector_type v, void* new_val){
if( v->no_e >= v->cur_cap ){
/*** reallocate a larger array ***/
v->cur_cap += (v->cur_cap) ? v->cur_cap : 2;
v->e_array = realloc(v->e_array, v->cur_cap*(v->e_sz))
}
/*** copy new_val in the array at index v->no_e ***/
/*** TO BE DONE START ***/
if(v->e_type == 1)
memcpy(((int*)v->e_array) + v->no_e*(v->e_sz), new_val, v->e_sz);
else if(v->e_type == 2)
memcpy(((double*)v->e_array) + v->no_e*(v->e_sz), new_val, v->e_sz);
else if(v->e_type == 3)
memcpy(((char*)v->e_array) + v->no_e*(v->e_sz), new_val, v->e_sz);
else if(v->e_type == 4)
memcpy(((float*)v->e_array) + v->no_e*(v->e_sz), new_val, v->e_sz);
/*** TO BE DONE END ***/
(v->no_e)++;
}
This function works for the char, but it appears that it's not inserting either int or double. I can't find out the error in the code.
... + v->no_e*(v->e_sz)
is wrong. You already cast to the appropriate type, so if you do +
on an array of items, you get pointer arithmetic for that specific type. It is sufficient just to do ... + v->no_e
because the item size is implicitly there based on the pointed-at type. This is why 1 byte chars work but nothing else.
Pointer arithmetic instead of array indexing is usually harder to read. I'd rewrite the code like this:
void* item;
switch(v->e_type)
{
case V_INT: item = &( (int*) v->e_array )[v->no_e]; break;
case V_DOUBLE: item = &( (double*) v->e_array )[v->no_e]; break;
case V_CHAR: item = &( (char*) v->e_array )[v->no_e]; break;
case V_FLOAT: item = &( (float*) v->e_array )[v->no_e]; break;
}
memcpy(item, new_val, v->e_sz);
Note how a few spaces here and there turns repetitive code much more readable and minimizes the chance for typo-related bugs. Also note that this code is taking advantage of [] having higher operator precedence than &.
The pointer arithmetic alternative is actually pretty OK too in this specific case. Many might find this more readable:
void* item;
switch(v->e_type)
{
case V_INT: item = (int*) v->e_array + v->no_e; break;
case V_DOUBLE: item = (double*) v->e_array + v->no_e; break;
case V_CHAR: item = (char*) v->e_array + v->no_e; break;
case V_FLOAT: item = (float*) v->e_array + v->no_e; break;
}
memcpy(item, new_val, v->e_sz);