#define FIZZ 1
#define BUZZ 2
struct {
uint8_t flags;
uint8_t next;
} static const nfo[] = {
{FIZZ+BUZZ,1},
{0,2},
{0,3},
{FIZZ,4},
{0,5},
{BUZZ,6},
{FIZZ,7},
{0,8},
{0,9},
{FIZZ,10},
{BUZZ,11},
{0,12},
{FIZZ,13},
{0,14},
{0,0}
} __attribute__((align(YOUR_L1D_LINE_SIZE)));
static const char* strs[] = {
[0] = "%u\n",
[FIZZ] = "fizz\n",
[BUZZ] = "buzz\n",
[FIZZ+BUZZ] = "fizzbuzz\n"
};
void fizzbuzz(uint32_t upTo)
{
uint32_t i, state;
for(i = state = 0; i < upTo; i++) {
printf(strs[nfo[state].flags], i);
state = nfo[state].next;
}
}
No divisibility tests at all. No branches besides loop and printf call. Space can be saved by using a bitfield, but masking it will add speed costs. .data: 0
.rodata: 30 + 4 * sizeof(void*) + strings
.text: depending on arch, but not much
Assuming call to printf has no cost and the caches are hot, a modern x86 cpu could execute one iteration of this loop in 1 cycle (issuing 2 loads, one add, one cmp, one branch)I have no compiler and am typing this on a phone so please forgive typos, if any