For some reason, adding n
to printf()
changes the behaviour of below code. The code without n
prints (null)
whereas the code with n
leads to Segmentation fault
.
Printf.c
#include <stdio.h> int main(int argc, char* argv[]){ printf("%s", argv[1]); }
Printf.c – Output
$ gcc -o Printf Printf.c $ ./Printf (null)
Printf_Newline.c
#include <stdio.h> int main(int argc, char* argv[]){ printf("%sn", argv[1]); }
Printf_Newline.c – Output
$ gcc -o Printf_Newline Printf_Newline.c $ ./Printf_Newline Segmentation fault (core dumped)
I am curious to understand the reason behind this.
Advertisement
Answer
Both are undefined behavior, so an answer could stop right here.
But there’s at least an explanation for the output of (null)
. This is an extension in glibc
(the GNU C library). Passing 0
for %s
in printf()
is considered undefined in the C standard and therefore could very well result in a crash. The developers of glibc
decided to do something meaningful instead.
The reason the second crashes nevertheless is that with the newline, the compiler decides to optimize: Instead of printf("%sn", argv[1])
, it executes puts(argv[1])
, which is semantically equivalent according to the C standard, therefore an allowed optimization. But glibc
s “(null)-trick” is only implemented in printf()
.
There’s another undefined behavior in your program: You potentially access argv
out of bounds. There’s no guarantee what value you will find at argv[i]
when i > argc
. There’s a slight chance argc
could be 0, so you could experience anything else as well.