简体   繁体   中英

Do the following statements assign either physical or virtual address to a pointer?

From https://stackoverflow.com/a/2761494/156458

neither C nor C++ provides a strictly defined feature that would allow you to assign a specific physical address to a pointer. So your question about "how one would assign 0 address to a pointer" formally has no answer. You simply can't assign a specific address to a pointer in C/C++. However, in the realm of implementation-defined features, the explicit integer-to-pointer conversion is intended to have that effect. So, you'd do it as follows

 uintptr_t address = 0; void *p = (void *) address; 

Note, that this is not the same as doing

 void *p = 0; 

The latter always produces the null-pointer value, while the former in general case does not. The former will normally produce a pointer to physical address 0, which might or might not be the null-pointer value on the given platform.

I am surprised to find it out that void *p = 0 doesn't assign either physical or virtual address 0 but a null pointer of void to the pointer.

The quote also says that the "explicit integer-to-pointer conversion" can assign an address to a pointer.

Questions:

  1. in void *p = 0 , is there implicit conversion from 0 to void* ?

    Is the implicit conversion the same as explicit conversion (void *)0 , ie is void *p = 0 the same as void *p = (void*) 0 ?

    Does void *p = (void*) 0 produce a pointer to either physical or virtual address 0 or a null pointer of void ?

  2. If I use a nonzero number, eg void *p = 123 , is there implicit conversion from 123 to void * ?

    Is the implicit conversion the same as explicit conversion (void *) 123 ?

    Will either void *p = 123 or void *p = (void *)123 make p a pointer to either physical or virtual address 123 ?

    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; int addr = 123; void *p = (void *)addr; ? I create it by replacing unitptr_t with int in the first example in the quote.

Thanks.

If you say

char *p = 0x12345;

you will probably assign p to point to address 0x12345 . Whether that's a virtual or a physical address we can't say; that depends on your machine and how it's configured. (But if your machine uses virtual memory, and if you're writing an ordinary user program, then it's certainly a virtual address.)

In the above I said "probably", in part because assigning an integer to a pointer is not, strictly speaking, well-defined. So to be on the safe side, you would write

char *p = (char *)0x12345;

This will, again, assign p to point to address 0x12345 .

But then we come to the special cases. If you write

char *p = 0;

or

char *p = (char *)0;

the question is, have you assigned p to point to address 0 ? And the answer is, probably, on any conventional machine, but this is not guaranteed, because there's a special case for null pointers.

It's not that p = 0 will not assign p to point to address 0 -- it's that it might not . On a machine where the internal representation of a null pointer is not all-bits-0, the assignment p = 0 will set p to that null pointer value, and p will therefore not point to address 0.

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.

  1. 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 , ie 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.

  1. If I use a nonzero number, eg 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; 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM