In complement of Sourav Ghosh's answer; an important notion is that of undefined behavior, which is tricky. Be sure to read Lattner's blog: What Every C Programmer Should Know About Undefined Behavior. See also this.
So, leaving on purpose (or perhaps depending upon) some undefined behavior in your code is intentional malpractice. Don't do that. In the very rare cases you want to do that (I cannot see any), please document it and justify yourself in some comment.
Be aware that if indeed printf
is implemented by the C standard library, it can be (and often is) specially handled by the compiler (with GCC and GNU libc, that magic might happens using internally __builtin_printf
)
The C99 & C11 standards are partially specifying the behavior of printf
but does leave some undefined behavior cases to ease the implementation. You are unlikely to full understand or be able to mimic these cases. And the implementation itself could change (for example, on my Debian Linux, an upgrade of libc
might change the undefined behavior of printf
)
If you want to understand more printf
study the source of some C standard library implementation (e.g. musl-libc, whose code is quite readable) and of the GCC implementation (assuming a Linux operating system).
But maintainers of GNU libc and of GCC (& even of the Linux kernel, thru syscalls) stay free to change the undefined behavior (of printf
and anything else)
In practice, always compile with gcc -Wall
(and probably also -g
) if using GCC. Don't accept any warnings (so improve your own code till you get none).