Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure ANSI-C: make generic array

Is it possible to replicate an generic array in pure ANSI-C?

I have this struct which holds an array (for floats at the moment) and some variables like size and capacity for mutation in the array.

typedef struct _CustomArray
{
    float* array; //the array in which the objects will be stored
    int size; //the current size of the array
    int capacity; //the max capacity of the array
} CustomArray; 

I use this struct so I can make an array in pure C where I can add/remove items, dynamically expand the array size when needed etc. all the things a "standard" array does, except it is made in C only. And now I want to make this so that when you initialize this struct you can set the datatype of the elements it should hold, at this moment it's only capable of storing float datatypes, but I want to make it so that it can store any datatype/other structs. But I don't know if this is even possible.

At this moment the function to make this array is:

CustomArray* CustomArray_Create(int initCapacity, /*type elementType*/)
{
    CustomArray* customArray_ptr; //create pointer to point at the structure
    float* internalArray = (float*)malloc(sizeof(float) * initCapacity); //create the internal array that holds the items
    if(internalArray != NULL)
    {
        CustomArray customArray = { internalArray, 0, initCapacity }; //make the struct with the data
        customArray_ptr = &customArray; //get the adress of the structure and assign it to the pointer
        return customArray_ptr; //return the pointer
    }
    return NULL;
}

Is it possible to give a datatype as parameter so I can malloc memory for that datatype and cast it as that given datatype in an array dynamically?

Thanks in advance,

Marnix van Rijswijk

like image 482
Marnix v. R. Avatar asked Dec 12 '22 17:12

Marnix v. R.


1 Answers

Your code has a serious problem... you're returning the address of a local variable (CustomArray) and when the function returns that variable is destroyed so you cannot keep using it with the pointer. You have to malloc also that structure so that the memory will be still available once the function returns.

About making the type a parameter you can get somewhat close using macros... for example with something like:

#include <stdlib.h> 
#define DefArray(type) \
typedef struct T_##type##Array {\
    type *array; \
    int size, capacity; \
} type##Array; \
static type##Array *type##ArrayCreate(int capacity)\
{\
    type##Array *s = malloc(sizeof(type##Array));\
    if (!s) return NULL;\
    s->array = malloc(sizeof(type) * capacity);\
    if (!s->array) { free(s); return NULL; }\
    s->size=0; s->capacity = capacity;\
    return s;\
}

Then you can use it this way

#include "customarray.h"
DefArray(float);
DefArray(double);

void foo()
{
    floatArray *fa = floatArrayCreate(100);
    ...
}

Note that you've to use macros to define all your custom functions. Note also that this approach will duplicate the code in each module (I'd say not a big issue but if you can't use C++ probably your target platform is pretty small). With a slightly more complex approach you could generate separate .h file and .c files for the implementation.

like image 130
6502 Avatar answered Dec 28 '22 06:12

6502