Integer representation of pointer - c++

What is the integer representation of pointer?
A pointer value is a safely-derived pointer to a dynamic object only
if it has an object pointer type and it is one of the following:
[...]
— the result of a reinterpret_cast of an integer representation of a safely-derived pointer value;
[...]
My doubt is about the following:
Type int is less than any pointer to type. In particular, pointer to cannot be casted to int using reinterpret_cast.

The term is defined in the very next paragraph of the standard.
An integer value is an integer representation of a safely-derived pointer only if its type is at least as large as
std::intptr_t and it is one of the following:
— the result of a reinterpret_cast of a safely-derived pointer value;
— the result of a valid conversion of an integer representation of a safely-derived pointer value;
— the value of an object whose value was copied from a traceable pointer object, where at the time of
the copy the source object contained an integer representation of a safely-derived pointer value;
— the result of an additive or bitwise operation, one of whose operands is an integer representation of a
safely-derived pointer value P, if that result converted by reinterpret_cast<void*> would compare
equal to a safely-derived pointer computable from reinterpret_cast<void*>(P).

Related

What would happen if T1 is not stricter than T2 in reinterpret-casting?

[expr.reinterpret.cast]/7:
Any object pointer type T1* can be
converted to another object pointer type cv T2*. This is exactly
equivalent to static_cast<cv T2*>(static_cast<cv void*>(T1_var))
(which implies that if T2's alignment requirement is not stricter than
T1's, the value of the pointer does not change and conversion of the
resulting pointer back to its original type yields the original value)
Am I wondering that there's no limitation while casting a pointer from one type to another using reinterpret_cast. The only thing I notice, when reading the given quote, is that the target type shall be stricter than the original type, [otherwise] not mentioned in this quote. For example
int *p = 0;
double *q = reinterpret_cast<double *>(p)
Here alignof(int) is not greater (stricter?) than or equal alignof(double). Although the compiler gives no errors or even warnings, I think in this case, q pointer holds an unspecified value? and dereferencing it is undefined behavior.
So does this mean converting a pointer of type T1* into T2*, the resulting pointer always has an unspecified value as long as static_assert(alignof(T1) >= alignof(T2)) fails?
So does this mean converting a pointer of type T1* into T2*, the
resulting pointer always has an unspecified value as long as
static_assert(alignof(T1) >= alignof(T2)) fails?
Not really. The result is only (but always) unspecified if the actual address of the T1 type doesn't fulfil the alignment requirements of the T2 type. It may do so, in which case the behaviour is well-defined.
The paragraph from the Standard you cite states the equivalence of a reinterpret_cast operation to two static_cast operations via an intermediate void* pointer. And, from the Standard, in the previous section about static_cast (bolding for emphasis mine):
8.5.1.9 Static cast     [expr.static.cast]
13     A prvalue of type “pointer to cv1
void” can be converted to a prvalue of type “pointer to cv2 T”,
where T is an object type and cv2 is the same cv-qualification as,
or greater cv-qualification than, cv1. If the original pointer value
represents the address A of a byte in memory and A does not satisfy
the alignment requirement of T, then the resulting pointer value is
unspecified. Otherwise, if the original pointer value points to an
object a, and there is an object b of type T (ignoring
cv-qualification) that is pointer-interconvertible (6.7.2) with a, the
result is a pointer to b. Otherwise, the pointer value is unchanged by
the conversion.

Shall a pointer to an array compare equal to a pointer to its first element?

Imagine that I have an array int x[10]; and in my implementation of C++ abstract machine a pointer to the array does not compare equal to a pointer to its "first" element (the result of the array-to-pointer conversion applied to x) but compares equal a pointer to the "last" element x[9]. I.e. (void*)x == (void*)&x is false and (void*)&x[9] == (void*)&x is true.
Would such implementation be conforming? The only thing I know it "violates" is a non-normative Note in [basic.compound]/4:
[Note: An array object and its first element are not pointer-interconvertible, even though they have the same address.  — end note]
See [basic.compound (6.9.2)]/3:
A value of a pointer type that is a pointer to [...] an object represents the address of the first byte in memory occupied by the object.
Since x[0] is the first element of the array (and arrays are specified to have no initial padding), the first byte of x must be the same as the first byte of x[0].
In [conv.ptr]/2 it says:
A prvalue of type “pointer to cv T ”, where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The pointer value (6.9.2) is unchanged by this conversion
I don't see any other way to interpret that than that the value of (void *)&x represents the address of the first byte of x .

Assign memory address stored in int to int

Assuming the value of uint32_t x is an address. How can I get the value behind this address?
My try was to simply assign the address to a pointer.
int*y = x;
But x is not an int pointer, it's just int with an address as value.
An integer type which is large enough to represent all data pointers can be converted into a pointer using reinterpret_cast or an explicit conversion. The pointer can be indirected to get the pointed value using the indirection operator.
Note that uint32_t is not guaranteed to be large enough to be able to represent all pointer values (and in fact will not be enough on modern 64 bit cpus). uintptr_t is meant precisely for this purpose.
Note that if the pointed address does not contain an object (of compatible type), then behaviour will be undefined.
In C++ this can be done using reinterpret_cast
8.5.1.10 Reinterpret cast [expr.reinterpret.cast]
...
5. A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. [Note: Except as described in 6.6.4.4.3, the result of such a conversion will not be a safely-derived pointer value. —end note]
And the rules in 6.6.4.4.3 state:
An integer value is an integer representation of a safely-derived pointer only if its type is at least as large as std::intptr_t and it is one of the following:
—(3.1) the result of a reinterpret_cast of a safely-derived pointer value;
—(3.2) the result of a valid conversion of an integer representation of a safely-derived pointer value;
—(3.3) the value of an object whose value was copied from a traceable pointer object, where at the time of the copy the source object contained an integer representation of a safely-derived pointer value;
—(3.4) the result of an additive or bitwise operation, one of whose operands is an integer representation of a safely-derived pointer value P, if that result converted by reinterpret_cast<void*> would compare equal to a safely-derived pointer computable from reinterpret_cast<void*>(P).
So if x (in the question) has a type at least as large as std::intptr_t and is already an integral representation of a safely derived pointer as per the rules above, you will be able to get the value behind the address stored in x.

Pointer casting:can the Pointer has value?

can the Pointer have value??
so In which case is it used
int num=100;
int* iptr=NULL;
iptr=reinterpret_cast<int*>(num);
printf("%d \n",num);
printf("%d \n",num);
result
100
100
Mappings between pointers and integers are implementation-defined.
Conversion of an integer to a pointer using reinterpret_cast will not be a safely-derived pointer value except under certain conditions. Those conditions are not met in your example.
Citation from CPP draft (N4713):
8.5.1.10 Reinterpret cast
...
6. A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. [ Note:
Except as described in 6.6.4.4.3, the result of such a conversion will not be a safely-derived pointer value.
—end note ]
The conditions for Safely-derived pointers.
6.6.4.4.3 Safely-derived pointers
...
2 A pointer value is a safely-derived pointer to a dynamic object only if it has an object pointer type and it is one of the following:
(2.1) — the value returned by a call to the C++ standard library implementation of ::operator new(std::size_t) or ::operator new(std::size_t, std::align_val_t);
(2.2) — the result of taking the address of an object (or one of its subobjects) designated by an lvalue resulting from indirection through a safely-derived pointer value;
(2.3) — the result of well-defined pointer arithmetic using a safely-derived pointer value;
(2.4) — the result of a well-defined pointer conversion of a safely-derived pointer value;
(2.5) — the result of a reinterpret_cast of a safely-derived pointer value;
(2.6) — the result of a reinterpret_cast of an integer representation of a safely-derived pointer value;
(2.7) — the value of an object whose value was copied from a traceable pointer object, where at the time of the copy the source object contained a copy of a safely-derived pointer value.

Can the NULL macro actually be a nullptr?

According to the draft of the standard N4713 (7.11/1):
A null pointer constant is an integer literal (5.13.2) with value zero or a prvalue of type std::nullptr_t.
and 21.2.3/2:
The macro NULL is an implementation-defined null pointer constant.
follow that NULL can be defined as nullptr. Same is mentioned on cppreference:
#define NULL 0
//since C++11
#define NULL nullptr
At the same time "Additive operators" clause says (8.5.6/7):
If the value 0 is added to or subtracted from a null pointer value, the result is a null pointer value. If two null
pointer values are subtracted, the result compares equal to the value 0 converted to the type std::ptrdiff_t.
Hence the following code should be valid:
0 + nullptr;
nullptr - nullptr;
but because of the lack of +/- operators for std::nullptr_t the code is invalid.
Is there something that I didn't take into account or NULL macro can't be actually defined as nullptr?
While nullptr is a null pointer constant, it is not a null pointer value. The latter is a value of some pointer type, which std::nullptr_t is not.
Reference:
A null pointer constant is an integer literal (5.13.2) with value zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is
distinguishable from every other value of object pointer or function pointer type. Such a conversion is called
a null pointer conversion. [...]
7.11/1 in N4659, emphasize mine
So NULL can indeed be nullptr without providing the arithmetic operators.
nullptr is a null pointer literal, and although the result of converting nullptr to a pointer type is the null pointer value, nullptr itself isn't of a pointer type, but of type std::nullptr_t. The arithmetic works if you do convert the nullptr to a pointer type:
0 + (int*)nullptr;
(int*)nullptr - (int*)nullptr;
Can the NULL macro actually be a nullptr?
Yes, because nullptr is a null pointer literal.
Note that prior to C++11, the all of the null pointer literals in C++ happened to also be integer literals, so this bad code: char c = NULL; used to work in practice. If NULL is defined as nullptr, that code no longer works.
The keyword nullptr denotes the pointer literal. It is a prvalue of type std::nullptr_t. There exist implicit conversions from nullptr to null pointer value of any pointer type and any pointer to member type.
nullptr itself is not a pointer value nor pointer. Thus arithmetic operations are not applicable to nullptr.
For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type.
For subtraction, one of the following shall hold:
(2.1) both operands have arithmetic or unscoped enumeration type; or
(2.2) both operands are pointers to cv-qualified or cv-unqualified versions of the same completely-defined object type; or
(2.3) the left operand is a pointer to a completely-defined object type and the right operand has integral or unscoped enumeration type.
std::nullptr_t is none of those, hence std::nullptr cannot participate in additive operations.
Note that not even all pointer values can participate. For example, function pointer values and void pointer values cannot, even though either can be a null pointer value.