1

I found something rather odd with printf.

When I do the following

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

I get a segfault.

But when I do this:

printf (".%s\n", (char *)NULL);

the output is below and no crash.

.(null)

Does anyone know why the behavior difference?

Haris
  • 12,120
  • 6
  • 43
  • 70
LucyY
  • 39
  • 1
  • 4
    Undefined behavior can include *anything*, including this. – EOF Mar 21 '16 at 17:48
  • [See this answer (to the question I think this is a duplicate of) for a decently simple explanation](http://stackoverflow.com/a/11589443/1287251). Short answer: `printf("%s\n", ...)` is converted to `puts`, which segfaults on `NULL`, but `printf(".%s\n", ...)` uses the actual `printf` function which converts `NULL` to `(null)`. – Cornstalks Mar 21 '16 at 17:49
  • 2
    Stop doing odd/bad things and odd/bad things will stop happening. – Martin James Mar 21 '16 at 17:49
  • You might find something completely different happens on a different target/compiler. As @EOF said, undefined behaviour is just that - learn never to be surprised by what it actually ends up doing – doctorlove Mar 21 '16 at 17:50
  • What OS and compiler? – HolyBlackCat Mar 21 '16 at 17:50
  • 2
    @Olaf: Incorrect. If you want to pass a null pointer to `printf`, you *need* to cast it to the appropriate pointer type. Without the cast, if `NULL` is defined as `0`, you're passing an `int`, not a `char*`. That doesn't really apply in this case, since the behavior is undefined anyway, but it does apply to `printf("%p\n", (void*)NULL)`. But passing a pointer to a variadic function is (I think) the only case where you really need to cast `NULL` to a pointer type. – Keith Thompson Mar 21 '16 at 17:57
  • @KeithThompson: Heck, I always forget about varargs. Thanks. Btw. things are even worse, as a null pointer might have different representation, depending on the target type. – too honest for this site Mar 21 '16 at 18:01

1 Answers1

0

If you look at the generated assembly code, you will see that printf ("%s\n",…) has been optimized by the compiler into a call to puts, whereas other format strings do not lend themselves to this trick.

It so happens that on your platform, the printf function detects null pointers and kindly avoids to crash, whereas the puts function doesn't.

The distinction doesn't matter: it is undefined behavior to pass a null pointer to printf for %s. Do no do it ever, even if, on your particular compilation platform, you were lucky the second time.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • This answer is a copy from the duplicate answer. Better close as duplicate then answer this. – SergeyA Mar 21 '16 at 17:54
  • @SergeyA I'm going to assume that English is not your native language and that you are not really accusing me of plagiarism just because my answer states the same information that already exists elsewhere. – Pascal Cuoq Mar 21 '16 at 17:58
  • I didn't mean to accuse you of anything, I just mentioned that it is a duplication of the same detail. SO promotes closig duplicates as such, rather than answering them. – SergeyA Mar 21 '16 at 18:14
  • @SergeyA In this case, I am sorry to tell you that “This answer is a copy from the duplicate answer” does not mean what you wanted to say, and the question is now closed. – Pascal Cuoq Mar 21 '16 at 18:15
  • Yes, I should probably have said 'copy of' rather than 'copy from'. My apologies for improper use of wording. – SergeyA Mar 21 '16 at 18:16
  • @SergeyA That's like arguing that “Wikipedia is a copy of the Encyclopedia Britannica” is more correct than “Wikipedia is a copy from the Encyclopedia Britannica”. – Pascal Cuoq Mar 22 '16 at 06:58