We can likewise claim about C that "0 in C is typed in theory and sort of untyped in practice" because constant expressions of integer type that evaluate to 0 can serve as null pointers of any type:
char *p = 0; // no cast required
if (p == 0) ... // no cast required
time_t t = time(0); // fine
char *q = 1; // error; requires (char *) 1.
We can't think of this 0 as an object; it's just a source code token that provides a null pointer of the right type, which is statically obvious from the use.The only time it's a problem is in unsafe interfaces:
int old_style_string_fun();
int variadic_fun(char *first, ...);
old_style_string_fun(0);
variadic_fun("first", 0);
Here, the wrong type is inferred; the 0 just behaves like the ordinary constant of type int. A null pointer to char was intended, which requires (char *) 0 must be used.None of this challenges the fact that we can have a variable of type int, whose value is 0.