Search code examples
carrayspointersvoiddereference

Dereferencing pointer to array of void


I am attempting to learn more about C and its arcane hidden powers, and I attempted to make a sample struct containing a pointer to a void, intended to use as array. EDIT: Important note: This is for raw C code.

Let's say I have this struct.

    typedef struct mystruct {
        unsigned char foo;
        unsigned int max;
        enum data_t type;
        void* data;

    } mystruct;

I want data to hold max of either unsigned chars, unsigned short ints, and unsigned long ints, the data_t enum contains values for those 3 cases.

    enum Grid_t {gi8, gi16, gi32}; //For 8, 16 and 32 bit uints.

Then I have this function that initializes and allocates one of this structs, and is supposed to return a pointer to the new struct.

    mystruct* new(unsigned char foo, unsigned int bar, long value) {
        mystruct* new;
        new = malloc(sizeof(mystruct)); //Allocate space for the struct.
        assert(new != NULL);
        new->foo = foo;
        new->max = bar;
        int i;
        switch(type){
            case gi8: default:
                new->data = (unsigned char *)calloc(new->max, sizeof(unsigned char));
                assert(new->data != NULL);
                for(i = 0; i < new->max; i++){
                    *((unsigned char*)new->data + i) = (unsigned char)value;
                    //Can I do anything with the format new->data[n]? I can't seem
                    //to use the [] shortcut to point to members in this case!
                }
            break;
        }
        return new;
    }

The compiler returns no warnings, but I am not too sure about this method. Is it a legitimate way to use pointers?

Is there a better way©?

I missed calling it. like mystruct* P; P = new(0,50,1024);

Unions are interesting but not what I wanted. Since I will have to approach every specific case individually anyway, casting seems as good as an union. I specifically wanted to have much larger 8-bit arrays than 32-bits arrays, so an union doesn't seem to help. For that I'd make it just an array of longs :P


Solution

  • Is type supposed to be an argument to the function? (Don't name this function or any variable new or any C++ programmer who tries to use it will hunt you down)

    If you want to use array indices, you can use a temporary pointer like this:

    unsigned char *cdata = (unsigned char *)new->data;
    cdata[i] = value;
    

    I don't really see a problem with your approach. If you expect a particular size (which I think you do given the name gi8 etc.) I would suggest including stdint.h and using the typedefs uint8_t, uint16_t, and uint32_t.