The %s conversion of printf states that the corresponding argument a pointer to the initial element of an array of character type. A null pointer does not point to the initial element of any array of character type, and thus the behavior of the following is undefined:

char *foo = NULL;
printf("%s", foo); /* undefined behavior */

However, the undefined behavior does not always mean that the program crashes — some systems take steps to avoid the crash that normally happens when a null pointer is dereferenced. For example Glibc is known to print

(null)

for the code above. However, add (just) a newline to the format string and you will get a crash:

char *foo = 0;
printf("%s\\n", foo); /* undefined behavior */

In this case, it happens because GCC has an optimization that turns printf("%s\\n", argument); into a call to puts with puts(argument), and puts in Glibc does not handle null pointers. All this behavior is standard conforming.

Note that null pointer is different from an empty string. So, the following is valid and has no undefined behaviour. It’ll just print a newline:

char *foo = "";
printf("%s\\n", foo);