Is it legal for a pointer to point to a C++ register?

In most cases where a CPU has memory-mapped registers, compilers that use some of them will specify which ones they use. Registers that the compiler's documentation says it doesn't use may be accessed using volatile-qualified pointers, just like any other kind of I/O registers, provided they don't affect the CPU state in ways the compiler doesn't expect. Reads of registers that may used by the compiler will generally yield whatever value the compiler's generated code happened to leave there, which is unlikely to be meaningful. Writes of registers that are used by the compiler will be likely to disrupt program behavior in ways that cannot be usefully predicted.


Is it legal for a pointer to point to C++ register?

Yes and no. In C++ the register keyword, if not deprecated, is a suggestion to the compiler, not a demand.

Whether the compiler implements a pointer to register depends on whether the platform supports pointers to registers or the registers are memory mapped. There are platforms where some registers are memory mapped.

When the compiler encounters a POD variable declaration, the compiler is allowed to use a register for the variable. However, if the platform does not support pointers to registers, the compiler may allocate the variable in memory; especially when the address of the the variable is taken.

Given an example:

int a; // Can be represented using a register.  

int b;
int *p_b = &b;  // The "b" variable may no longer reside in a register
               // if the platform doesn't support pointers to registers.  

In many common platforms, such as the ARM processors, the registers are located within the processor's memory area (a special area). There are no address lines or data lines for these registers that come out of the processor. Thus, they don't occupy any space in the processor's address space. There are also no ARM instructions to return the address of a register. So for ARM processors, the compilers would change the allocation of a variable from register to memory (external to the processor) if the code uses the address of the variable.


Is it legal for a pointer to point to C++ register?

Yes.

Would that compiler be considered standard-compliant?

Sure.

C++ is not aware of "registers", whatever that is. Pointers point to objects (and functions), not to "memory locations". The standard describes the behavior of the program and not how to implement it. Describing behavior makes it abstract - it's irrelevant what is used in what way and how, only the result is what matters. If the behavior of the program matches what the standard says, it's irrelevant where the object is stored.

I can mention intro.memory:

  1. A memory location is either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width.

and compund:

Compound types can be constructed in the following ways:

  • pointers to cv void or objects or functions (including static members of classes) of a given type,

[...] Every value of pointer type is one of the following:

  • a pointer to an object or function (the pointer is said to point to the object or function), or
  • a pointer past the end of an object ([expr.add]), or
  • the null pointer value for that type, or
  • an invalid pointer value.

[...] The value representation of pointer types is implementation-defined. [...]

To do anything useful with a pointer, like apply * operator unary.op or compare pointers expr.eq they have to point to some object (except edge cases, like NULL in case of comparisons). The notation of "where" exactly objects are stored is rather vague - memory stores "objects", memory itself can be anywhere.


For example, if compiler, for whatever reason(optimization reasons for example), uses register allocation for a variable(not talking about register keyword), we print the value of the reference to that variable, the compiler would return one of the reserved "address values"

std::ostream::operator<< calls std::num_put and conversion for void* is %p facet.num.put.virtuals. From C99 fprintf:

[The conversion %]p

The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.

But note that from C99 fscanf:

[The conversion specified %]p

Matches an implementation-defined set of sequences, which should be the same as the set of sequences that may be produced by the %p conversion of the fprintf function. The corresponding argument shall be a pointer to a pointer to void. The input item is converted to a pointer value in an implementation-defined manner. If the input item is a value converted earlier during the same program execution, the pointer that results shall compare equal to that value; otherwise the behavior of the %p conversion is undefined.

What is printed has to be unique for that object, that's all. So a compiler has to pick some unique value for addresses in registers and print them whenever the conversion is requested. The conversions from/to uintptr_t will have also be implemented in an implementation-defined manner. But it would be all in implementation - the implementation details of how the behavior of the code is achieved is invisible to a C++ programmer.