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
byprintf
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.