Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this code use a *char as a buffer pointer?

Tags:

c

char

pointers

In looking for circular buffer code to reuse, I've come across a use of char which confuses me

typedef struct CircularBuffer
{
    void *buffer;     // data buffer
    void *buffer_end; // end of data buffer
    size_t capacity;  // maximum number of items in the buffer
    size_t count;     // number of items in the buffer
    size_t sz;        // size of each item in the buffer
    void *head;       // pointer to head
    void *tail;       // pointer to tail
} CircularBuffer;

void cb_push_back(CircularBuffer *cb, const void *item)
{
    if(cb->count == cb->capacity)
        // handle error
        memcpy(cb->head, item, cb->sz);

    ////////////// here's the part I don't understand //////////
    cb->head = (char*)cb->head + cb->sz;
    //////////////////////////////////////////////////////////

    if(cb->head == cb->buffer_end)
        cb->head = cb->buffer;
    cb->count++;
}

Why cast this void pointer to a char? Is this some sort of C idiom (I have very limted C expereience)? A away convenient way to increment a pointer perhaps?

The use of a char for the position pointer comes up again in some different buffer code as well:

/**< Circular Buffer Types */
typedef unsigned char INT8U;
typedef INT8U KeyType;
typedef struct
{
    INT8U writePointer; /**< write pointer */
    INT8U readPointer;  /**< read pointer */
    INT8U size;         /**< size of circular buffer */
    KeyType keys[0];    /**< Element of ciruclar buffer */
} CircularBuffer;

Again, this looks like some sort of handy trick that C programmers know about, something about pointers being easy to manipulate if they're chars. But I'm really just speculating.

like image 719
morgancodes Avatar asked Dec 06 '22 23:12

morgancodes


1 Answers

The cast to char * is to make pointer arithmetic perform correctly if you want to move the pointer in one-byte steps; this always works because char have, by definition, the size of 1 byte. Pointer arithmetic with void * pointers, instead, is not defined by the C standard, because void doesn't specify a size for a single item.

Another common C idiom (related to this) is to use unsigned char * when you want to access some memory as "raw bytes" (the unsigned type lets you access the unsigned value of each byte without casts); it's often used also typedefed (something along the lines of typedef unsigned char byte;) to make it extra clear that you don't want to interpret the memory as characters, but as raw bytes.

like image 134
Matteo Italia Avatar answered Dec 29 '22 01:12

Matteo Italia