Bird
Raised Fist0
Embedded Cprogramming~20 mins

Ring buffer for UART receive in Embedded C - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Ring Buffer Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this ring buffer read function?

Consider this simplified ring buffer read function for UART data. What will be the returned value when ring_buffer_read() is called?

Embedded C
typedef struct {
    unsigned char buffer[4];
    unsigned int head;
    unsigned int tail;
} RingBuffer;

RingBuffer rb = {{'A', 'B', 'C', 'D'}, 2, 0};

unsigned char ring_buffer_read(RingBuffer *rb) {
    if (rb->head == rb->tail) {
        return 0; // Buffer empty
    }
    unsigned char data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % 4;
    return data;
}

int main() {
    unsigned char c = ring_buffer_read(&rb);
    printf("%c", c);
    return 0;
}
AA
BB
CC
DD
Attempts:
2 left
💡 Hint

Remember that tail points to the next byte to read.

❓ Predict Output
intermediate
2:00remaining
What is the value of tail after reading one byte?

Given the same ring buffer as before, what is the value of rb.tail after calling ring_buffer_read(&rb) once?

Embedded C
typedef struct {
    unsigned char buffer[4];
    unsigned int head;
    unsigned int tail;
} RingBuffer;

RingBuffer rb = {{'A', 'B', 'C', 'D'}, 2, 0};

unsigned char ring_buffer_read(RingBuffer *rb) {
    if (rb->head == rb->tail) {
        return 0; // Buffer empty
    }
    unsigned char data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % 4;
    return data;
}

int main() {
    ring_buffer_read(&rb);
    printf("%u", rb.tail);
    return 0;
}
A1
B2
C3
D0
Attempts:
2 left
💡 Hint

Tail moves forward by one position modulo buffer size.

❓ Predict Output
advanced
2:00remaining
What happens if head equals tail in this ring buffer?

What will ring_buffer_read() return if rb.head equals rb.tail?

Embedded C
typedef struct {
    unsigned char buffer[4];
    unsigned int head;
    unsigned int tail;
} RingBuffer;

unsigned char ring_buffer_read(RingBuffer *rb) {
    if (rb->head == rb->tail) {
        return 0; // Buffer empty
    }
    unsigned char data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % 4;
    return data;
}

int main() {
    RingBuffer rb = {{'A', 'B', 'C', 'D'}, 1, 1};
    unsigned char c = ring_buffer_read(&rb);
    printf("%d", c);
    return 0;
}
AA
B1
C0
DUndefined behavior
Attempts:
2 left
💡 Hint

When head equals tail, the buffer is empty.

❓ Predict Output
advanced
2:00remaining
What is the output after writing and reading in this ring buffer?

Given this code that writes a byte then reads one, what is printed?

Embedded C
typedef struct {
    unsigned char buffer[4];
    unsigned int head;
    unsigned int tail;
} RingBuffer;

void ring_buffer_write(RingBuffer *rb, unsigned char data) {
    rb->buffer[rb->head] = data;
    rb->head = (rb->head + 1) % 4;
}

unsigned char ring_buffer_read(RingBuffer *rb) {
    if (rb->head == rb->tail) {
        return 0;
    }
    unsigned char data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % 4;
    return data;
}

int main() {
    RingBuffer rb = {{0}, 0, 0};
    ring_buffer_write(&rb, 'X');
    unsigned char c = ring_buffer_read(&rb);
    printf("%c", c);
    return 0;
}
A0
BX
CA
DUndefined
Attempts:
2 left
💡 Hint

Write adds 'X' at head, then read returns from tail.

❓ Predict Output
expert
2:00remaining
How many bytes can this ring buffer hold before head catches tail?

Given a ring buffer of size 4, what is the maximum number of bytes it can hold before it appears full (head catches tail)?

Embedded C
typedef struct {
    unsigned char buffer[4];
    unsigned int head;
    unsigned int tail;
} RingBuffer;
A1
B4
C2
D3
Attempts:
2 left
💡 Hint

One slot is left empty to distinguish full from empty.

Practice

(1/5)
1. What is the main purpose of using a ring buffer for UART receive data?
easy
A. To encrypt UART data before processing
B. To increase the UART baud rate automatically
C. To convert UART data into parallel data
D. To store incoming data in a circular way to prevent data loss

Solution

  1. Step 1: Understand UART data flow

    UART data arrives asynchronously and can be lost if not stored properly.
  2. Step 2: Role of ring buffer

    A ring buffer stores data in a circular way so new data overwrites old only when full, preventing data loss.
  3. Final Answer:

    To store incoming data in a circular way to prevent data loss -> Option D
  4. Quick Check:

    Ring buffer = circular storage for UART data [OK]
Hint: Ring buffer means circular storage to avoid losing data [OK]
Common Mistakes:
  • Confusing ring buffer with baud rate control
  • Thinking it encrypts data
  • Assuming it converts data format
2. Which of the following is the correct way to declare a ring buffer array of size 64 bytes in embedded C?
easy
A. char ringBuffer[64];
B. int ringBuffer = 64;
C. char ringBuffer();
D. char ringBuffer[;]

Solution

  1. Step 1: Understand array declaration syntax

    In C, arrays are declared with type, name, and size in square brackets.
  2. Step 2: Check each option

    char ringBuffer[64]; correctly declares a char array of size 64. Others are invalid syntax or wrong types.
  3. Final Answer:

    char ringBuffer[64]; -> Option A
  4. Quick Check:

    Array declaration = type name[size] [OK]
Hint: Arrays use type name[size] syntax in C [OK]
Common Mistakes:
  • Using parentheses instead of brackets
  • Assigning size to variable instead of array
  • Leaving size empty or incorrect
3. Given this code snippet for a ring buffer with size 8:
uint8_t buffer[8];
uint8_t head = 0;
uint8_t tail = 0;

// Add data
buffer[head] = 0x55;
head = (head + 1) % 8;

// Add data
buffer[head] = 0xAA;
head = (head + 1) % 8;

// Read data
uint8_t data = buffer[tail];
tail = (tail + 1) % 8;
What is the value of data after this code runs?
medium
A. 0xAA
B. 0x55
C. 0x00
D. Undefined

Solution

  1. Step 1: Track buffer writes

    First, 0x55 is stored at buffer[0], head moves to 1. Then 0xAA stored at buffer[1], head moves to 2.
  2. Step 2: Read from tail

    Tail is 0, so reading buffer[0] returns 0x55, then tail moves to 1.
  3. Final Answer:

    0x55 -> Option B
  4. Quick Check:

    Read at tail=0 returns first stored value 0x55 [OK]
Hint: Read from tail pointer, which points to oldest data [OK]
Common Mistakes:
  • Reading from head instead of tail
  • Forgetting modulo wrap-around
  • Assuming data is 0xAA instead of 0x55
4. Identify the bug in this ring buffer code snippet for UART receive:
if ((head + 1) % BUFFER_SIZE == tail) {
    // Buffer full
    return;
}
buffer[head] = data;
head = (head + 1) % BUFFER_SIZE;
medium
A. Buffer full condition is correct, no bug
B. Buffer full check should use '==' instead of '!='
C. Buffer full check misses parentheses around addition
D. Buffer full condition should check if head == tail

Solution

  1. Step 1: Understand buffer full condition

    Buffer is full when next head position equals tail, meaning no space to write.
  2. Step 2: Analyze given condition

    The condition uses (head + 1) % BUFFER_SIZE == tail, which correctly detects full buffer.
  3. Final Answer:

    Buffer full condition is correct, no bug -> Option A
  4. Quick Check:

    Full when next head equals tail [OK]
Hint: Full buffer when next head equals tail [OK]
Common Mistakes:
  • Using wrong comparison operator
  • Forgetting modulo operation
  • Checking head == tail for full (actually empty)
5. You want to implement a function uart_receive_byte() that reads one byte from the ring buffer if available, or returns -1 if empty. Which code snippet correctly implements this?
hard
A. int uart_receive_byte() { if (tail == head) return 0; uint8_t data = buffer[tail]; tail = (tail + 1) % BUFFER_SIZE; return data; }
B. int uart_receive_byte() { if (head != tail) return -1; uint8_t data = buffer[head]; head = (head + 1) % BUFFER_SIZE; return data; }
C. int uart_receive_byte() { if (head == tail) return -1; uint8_t data = buffer[tail]; tail = (tail + 1) % BUFFER_SIZE; return data; }
D. int uart_receive_byte() { if (tail == head) return -1; uint8_t data = buffer[head]; head = (head + 1) % BUFFER_SIZE; return data; }

Solution

  1. Step 1: Check empty condition

    Buffer is empty when head equals tail, so return -1 in that case.
  2. Step 2: Read data and update tail

    Read from buffer[tail], then move tail forward with modulo wrap.
  3. Final Answer:

    Function returns -1 if empty, else data from tail and updates tail -> Option C
  4. Quick Check:

    Empty if head==tail; read from tail pointer [OK]
Hint: Return -1 if head==tail; read from tail and advance tail [OK]
Common Mistakes:
  • Checking wrong empty condition
  • Reading from head instead of tail
  • Returning 0 instead of -1 when empty
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard