Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Let's say a C++ compiler compiled code for an architecture where CPU registers are not memory-mapped. And also let's say that same compiler reserved some pointer values for CPU registers.

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

Would that compiler be considered standard-compliant?

From what I could gather (I haven't read the whole thing - Working Draft, Standard for Programming Language C++), I suspect that the standard doesn't mention such a thing as RAM memory or operative memory and it defines its own memory model instead and the pointers as representation of addresses (could be wrong).

Now since registers are also a form of memory, I can imagine that an implementation which considers registers to be a part of the memory model could be legal.

like image 916
wolfofuniverse Avatar asked Nov 02 '20 09:11

wolfofuniverse


People also ask

Can a pointer point to a register?

Completely depends on underlying machine architecture, but generally the answer is "no" for most modern machines, certainly x86. If you explicitly ask for a variable to be in a register then you can not take its address.

Can a pointer point to a type?

The pointers can point to any type if it is a void pointer. but the void pointer cannot be dereferenced. only if the complier knows the data type of the pointer variable, it can dereference the pointer and perform the operations.

Can pointers point to anything?

Any pointer can refer to any location in memory, so technically the statement is correct. With that said, you need to be careful when reinterpreting pointer types. A pointer basically has two pieces of information: a memory location, and the type it expects to find there. The memory location could be anything.

Can a pointer point to another pointer in C?

So, using a pointer to the pointer aka a double pointer in C, we can make the previous pointer point to another memory location.


2 Answers

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.

like image 83
KamilCuk Avatar answered Oct 03 '22 06:10

KamilCuk


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.

like image 8
Thomas Matthews Avatar answered Oct 03 '22 06:10

Thomas Matthews