Dealing with memory mapped registers, and ensuring the consistency of shared values in the face of interrupts, often requires use of the volatile qualifier in C.
Given the following code:
typedef struct sFIFO {
volatile uint16_t head;
volatile uint16_t tail;
const uint16_t length;
volatile uint8_t buffer[1];
} sFIFO;
#define FIFO_ADJUST_OFFSET_NI(fp_,v_) ((v_) % (fp_)->length)
static __inline__
int
fifo_push_head_ni (sFIFO * fp, uint8_t v)
{
uint16_t h = fp->head;
/* ... */
#if PICK_ONE
h = fp->head = FIFO_ADJUST_OFFSET_NI(fp, 1 + h);
#else
fp->head = h = FIFO_ADJUST_OFFSET_NI(fp, 1 + h);
#endif
/* ... */
}
consider these questions:
- Does the value of PICK_ONE affect the code generated for the statement variant it selects?
- Does your answer hold for all C compilers?
- Can you find the part of the C11standard (draft N1570) that supports your answers to the first and second questions?
If you're not interested in guessing, the answer for GCC is here, and text that supports that decision explicitly is in footnote 111 at section 6.5.16 paragraph 3 of N1570 (ISO/IEC 9899:2011), possibly supported by the last sentence of section 6.7.3 paragraph 7.
I was surprised by the answer.