Beginner Beginner - 1 month ago 16
C Question

Adding newline character to printf() changes code behaviour

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("%s\n", 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.

Answer Source

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("%s\n", argv[1]), it executes puts(argv[1]), which is semantically equivalent according to the C standard, therefore an allowed optimization. But glibcs "(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.