You can simplify args for printf by passing string literals as a format string, rather than using %s to print them. This exploits the fact that you know that there are no % characters in "fizz" or "buzz" . It is guaranteed that you can not use unused arguments for printing .
To make the source readable, pull the logic to select a format string from printf() and save it in a local variable.
#include <stdio.h> int main(void) { int n=30; for (int i = 1; i<=n; i++) { int fizzy = (i % 3 == 0); int buzzy = (i % 5 == 0); const char *fmt = (fizzy && buzzy) ? "fizzbuzz\n" : fizzy ? "fizz\n" : buzzy ? "buzz\n" : "%d\n"; printf(fmt, i); } }
It can be a good style, and perhaps make asm better, conditionally determine the arguments that you are going to pass, and then make one call, instead of writing the same function call with different arguments. This can be useful if most of the arguments you are going to pass are the same in different branches, which is not the case here.
It's usually best to just use puts (implicit \n added) or fputs to print constant lines that don't need formatting. Compilers know this, and even optimize printf("Hello World!\n"); or printf("%s\n", "Hello World!") before puts("Hello World!"); in trivial cases. This trick means that even fixed-line prints still cause the more expensive printf . (In addition to readability, this is one of the specific reasons why this is not a great choice in this particular case.)
gcc and clang compile this into asm, which works like the source does : printf always gets two arguments (in rdi and rsi ), but sometimes the format string doesn't use the 2nd argument. Change -O3 to -Os so that gcc uses a div instead of the multiplicative inverse.
They do not unroll the loop to fit the pattern modulo, or force - reduce the modulus to downward counters or something smart like you would do in handwritten asm FizzBuzz .
For an insidious way to write compact FizzBuzz, see CodeGolf.SE , where the format string %s%s%.d conditionally receives empty strings. %.d sets the precision to 0. Non-zero integers print normally, but 0 prints as an empty string.