The point is not that printf runs after fgets, but instead that its output is displayed after it.
This happens because standard output (the file descriptor you're writing on with printf) is line-buffered, i.e. the standard library defers prints after a newline character (\n) has been received for printing.
From man stdout:
The stream stdout is line-buffered when it points to a terminal.
Partial lines will not appear until fflush(3) or exit(3) is called, or
a newline is printed.
To investigate different results, edit your example to use fflush, or print on standard error using fprintf(stderr, ... .