C: why printing a null char with %s prints "(null)"?

It's undefined behavior, but it happens that on your implementation:

  • the int value of 0 that you pass is read by %s as a null pointer
  • the handling of %s by printf has special-case code to identify a null pointer and print (null).

Neither of those is required by the standard. The part that is required[*], is that a char used in varargs is passed as an int.

[*] Well, it's required given that on your implementation all values of char can be represented as int. If you were on some funny implementation where char is unsigned and the same width as int, it would be passed as unsigned int. I think that funny implementation would conform to the standard.


Well, for starters, you're doing it wrong. '\0' is a character and should be printed with %c and not %s. I don't know if this is intentional for experimentation purposes.

The actual binary value of \0 is, well, 0. You're trying to cast the value 0 to a char * pointer, which would result in an invalid reference and crash. Your compiler is preventing that with a special treatment of the %s value.

Valgrind won't catch it because it runs on the resulting binary, not the source code (you'd need a static analyzer instead). Since the compiler has already converted that call into a safe "null pointer" text, valgrind won't see anything amiss.

Tags:

C

Gcc