Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dereferencing void pointers

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.

like image 440
Zack Avatar asked Dec 04 '12 01:12

Zack


2 Answers

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];
like image 62
Chris Dodd Avatar answered Oct 21 '22 02:10

Chris Dodd


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?

Well, you've already done it on the LHS of that line:

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

To derefence buffer->elements[n] you will need to cast that as well.

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

Now the question is whether or not that cast is correct. I can't tell you that as you did not post the initialization of buffer->elements.

like image 43
Ed S. Avatar answered Oct 21 '22 01:10

Ed S.