Dereferencing void pointers

Zack picture Zack · Dec 4, 2012 · Viewed 25.4k times · Source

In the hope of gaining a better understanding of the answers given in this post, can someone please explain to me if the following circular buffer implementation is possible, and if not, why not.

#define CB_TYPE_CHAR     0
#define CB_TYPE_FLOAT    1

...

typedef struct CBUFF
{
    uint16 total;       /* Total number of array elements */
    uint16 size;        /* Size of each array element */
    uint16 type;        /* Array element type */
    uint16 used;        /* Number of array elements in use */
    uint16 start;       /* Array index of first unread element */
    void *elements;     /* Pointer to array of elements */
} CBUFF;

...

void cbRead(CBUFF *buffer, void *element)
{
    if (buffer->type == CB_TYPE_CHAR)
    {
    /* The RHS of this statement is the problem */
        *(char*)element = *(buffer->elements[buffer->start]);
    }

    /* Other cases will go here */

    buffer->start = (buffer->start + 1) % buffer->total;

    --buffer->used;
}

I understand that the LHS must be cast to char so that I can dereference the void pointer. I also understand that this code fragment:

buffer->elements[buffer->start]

gives the address of the 'buffer->start' element of the elements array, which I also want to dereference in order to get to the content of that address. Or at least that's what I take from K&R.

Given all that, how do I tell the compiler that the content of the memory at that address is a char, and that it is okay to dereference it? There is something going on here I just don't understand.

Answer

Chris Dodd picture Chris Dodd · Dec 4, 2012

buffer->elements is also a void * so you need to cast it before you can do anything with it:

*(char*)element = ((char *)buffer->elements)[buffer->start];