TL;DR: Most of what you are asking about is in the realm of implementation-specific behavior and language extensions. Consult your compiler documentation if you have genuine need for such behaviors.
- in
void *p = 0
, is there implicit conversion from 0
to void*
?
The initialization is non-conforming, but many compilers accept it as an extension. Those that do define the result however they want, but in practice they indeed provide an implicit conversion to void *
.
Because literal 0
is a "null pointer constant", because initializers perform the same conversions that simple assignment does, and because simple assignment has a special-case provision for assigning null pointer constants to pointers, yes, 0
is implicitly converted to type void *
. Furthermore, because 0
is a null pointer constant, such a conversion results in a null pointer of type void *
.
Is the implicit conversion the same as explicit conversion (void *)0
, i.e. is void *p = 0
the same as void *p = (void*) 0
?
There is good reason to expect that a compiler that accepts the former form will treat it exactly the same as the latter form, but again, the former is non-conforming and implementations that accept it as an extension define their own semantics for it.
Yes. C nowhere distinguishes between the effects of conversions specified explicitly via casts and automatic conversions between the same types.
Does void *p = (void*) 0
produce a pointer to either physical or virtual address 0 or a null pointer of void
?
It initializes p
to contain a null pointer (of type void *
). According to C, a null pointer does not point to any object, and C has no sense of addresses apart from those of objects or functions, so in at least this sense it is incorrect to interpret such a pointer as pointing to any particular address. The effect of dereferencing such a pointer is not defined by C, but it might be defined by some implementations -- possibly to attempt to access an object at address 0.
- If I use a nonzero number, e.g.
void *p = 123
, is there implicit conversion from 123
to void *
?
That initialization is non-conforming, but some compilers provide an implicit conversion as an extension.
Is the implicit conversion the same as explicit conversion (void *) 123
?
There is very good reason to expect that to be the case with a compiler that implements such an implicit conversion at all, but again, "extension".
Will either void *p = 123
or void *p = (void *)123
make p
a pointer to either physical or virtual address 123
?
That is implementation-defined. Again, C has no sense of addresses apart from those of objects or functions, and in particular it itself declines to specify the result of converting an integer to a pointer type, except for integers obtained by converting a pointer to integer in the first place, and for integer constant expressions with value 0.
On some implementations, however, converting an integer (other than an integer constant with value 0) to a pointer has the effect of interpreting the integer as an address, and converting to a pointer to that address, as if there were an object with that address. In a hosted C implementation, this will typically be a virtual address. In a standalone implementation, it will typically be a physical address. Some of implementations may extend this behavior to integer constants with value 0, too, which may or may not be inherently non-conforming.
If void *p = (void *)123
can't generate a pointer to either physical or virtual address 123
, can int addr = 123; void *p = (void *)addr;
? I create it by replacing unitptr_t
with int in the first example in the quote.
There is every reason to expect that the result of explicitly converting an int
variable with value 123 is exactly the same as that of explicitly converting an integer constant with value 123, but, technically, that it is implementation defined may leave room for conforming compilers to distinguish.