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.
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];