A request for a simple C code example that shows how you can use a generic or untyped (via void *) array

I am trying to create a generic (or untyped) array in C (I know that C ++ makes this easier). In a nutshell, I want to allocate an array to store an array of a certain known type (at run time). In a real implementation, this depends on user input.

I try to use the enum / struct script, following the tips found in several google hits, but I'm afraid that my inexperience with void pointers and the lack of a concrete example prevent me from getting a working piece of code, (Normally I would just buy a book, but I'm in the country where I don’t speak the language, and books on programming in English do not exist).

The problem boils down to the following simplification: I have an image (only 1D), the pixel value can be int, float or double. I have a function that will tell me the type. All I want to do is save the pixels in an array of the appropriate type. (In practice, these images are very large, and my motivation is to save memory and prevent writing blocks of code for each type.)

I tried something like the following, but maybe it's not the best (code snippet for a possible data structure):

enum type {
    typeint, typefloat, typedouble
};

struct genericarray {
    enum type type;
    void *storage;
};

Somehow I want to store these pixels in instances of generciarray. All my attempts so far have turned into a "warning: playing out the" void * pointer "of the parties, which I admit that I do not understand.

, , , . for-loops init. , .

+3
5

:

#include "stdlib.h"
#include "stdio.h"

// structure
enum type { typeint, typefloat, typedouble };

struct genericarray
{
    enum type type;
    void ** storage;
};

typedef struct genericarray genericarray;

// allocate
void allocate(long numItems, enum type varType, genericarray * array)
{
    (*array).type = varType;
    switch (varType)
    {
        case typeint:
            (*array).storage = malloc(numItems*sizeof(int));
            break;
        case typefloat:
            (*array).storage = malloc(numItems*sizeof(float));
            break;
        case typedouble:
            (*array).storage = malloc(numItems*sizeof(double));
    }
}

// release
void release(genericarray array)
{
    free(array.storage);
}

// usage
int main(int argCount, char ** argList)
{
    genericarray image_1;
    genericarray image_2;

    int iv;
    float fv;

    allocate(10, typeint, &image_1);
    allocate(10, typefloat, &image_2);

    ((int *)(image_1.storage))[5] = 42;
    iv = ((int *)(image_1.storage))[5];
    printf("image_1[5] = %d\n", iv);

    ((float *)(image_2.storage))[5] = 3.14159;
    fv = ((float *)(image_2.storage))[5];
    printf("image_2[5] = %f\n", fv);

    release(image_2);
    release(image_1);

    return 0;
}
+4
enum type {
    typeint, typefloat, typedouble
}

struct genericarray {
    enum type type;
    union { int i; float f; double d; } storage;
};

- , (imho.)

EDIT: void * int/float/double, : ( genericarray - void *)

array.storage = malloc(sizeof(int));

:

(*((int*)array.storage))

float type == typefloat ..

free(array.storage);
+2

, , - . , C , .

, , ( ), :

int *iptr;
double *dptr; 

switch (x.type)
{
    case typedouble:
        dptr = x.storage; // implcit conversion example
        // reference your "image" as dptr[i] now
        break;
    case typeint:
        iptr = (int *)x.storage; // explicit conversion, actually unnecessary
        // reference your "image" as iptr[i] now
        break;
 }
+2

, , ,

struct genericarray ga;
float fValue;

fValue = ga.storage[idx];

,

fValue = ((float*)ga.storage)[idx];

#define GET_STORAGE(_type, _src, _idx) \
  ((_type*)_src.storage)[_idx]
#define SET_STORAGE(_type, dst, _idx, _src) \
  ((_type*)_dst.storage)[_idx] = _src 

fValue = GET_STORAGE(float, ga, 3);

SET_STORAGE( float, ga, 3, sin(ang) );

"Chris Young" switch , .

+2

, , , , .

0
source

Source: https://habr.com/ru/post/1704521/


All Articles