Embedded C Code Tracing
Si-Ware Systems interview question (Egypt) · stage: Technical Interview · domain: Coding and Embedded · role: Embedded Engineer · difficulty: Medium · asked 3 times, last in June 2026
What they ask
The first technical round for the firmware side is centred on embedded systems and embedded C, and it starts after the obligatory walk through your graduation project. The format is distinctive: the interviewer introduces himself, gives you a short brief on what the company builds, asks some oral questions, and then puts written code in front of you to trace before handing over a paper exam. Several reports describe exactly that sequence, and the tracing part is where people come unstuck, because you cannot compile your way out of it.
The tracing questions. Short snippets where you state the output. Pointer arithmetic on an array of structs. A char that should have been unsigned char compared against 255. Integer promotion in a comparison between a signed and an unsigned value. A shadowed variable in an inner block. Operator precedence with a shift and a mask in the same expression. sizeof on an array parameter after it has decayed to a pointer. A static local that keeps its value across calls.
The concepts around them. volatile and the exact scenario where leaving it off breaks you, which is a hardware register the compiler decides to keep in a register. Where each object lives: stack, heap, .bss, .data, .rodata. Struct padding and how reordering fields shrinks the struct. What the vector table is, where the return address goes when an interrupt fires, and what you must not do inside an interrupt service routine.
The coding task
The representative hands on exercise, and the one that matches the work: a single producer single consumer ring buffer, written by the interrupt handler and read by the main loop. Capacity is a power of two. Implement push, pop, isEmpty and isFull using only a head and a tail index, with no separate count variable.
Examples
Capacity 4. Push 1, 2, 3 then pop twice: you get 1 then 2, and isEmpty is false because 3 is still there.
Push 1, 2, 3, 4 into a capacity of 4: the fourth push fails. With only head and tail and no count, one slot has to stay empty so that full and empty are distinguishable, and explaining that tradeoff out loud is most of the point of the question.
Pop from an empty buffer returns nothing and leaves the indices alone.
Constraints
- Capacity is a power of two, so the wrap is a mask and not a modulo. Say why that matters on a small microcontroller.
- No count variable and no lock.
- Then the real question: which variables need to be
volatile, which single index does each side write, and why that is what makes the structure safe without a critical section.
What they look for
Correct index arithmetic, and then the concurrency argument. Only the writer advances the head and only the reader advances the tail, each is a single aligned word write, so no mutual exclusion is needed as long as neither side caches the other's index. Candidates who reach for disabling interrupts get a working answer and miss the insight.