This is a new question in my \"I don\'t understand pointers in C and C++\" collection.
If I mix the bits of two pointers with equal values (pointing to the same mem
In [basic.compound]:
If an object of type
T
is located at an addressA
, a pointer of type cvT*
whose value is the addressA
is said to point to that object, regardless of how the value was obtained.
past
and val
have the same address, so they point to the same object. It doesn't matter that one is "one past the end" of the first row and the second is the first element of the second row. There is a valid object at that address, so everything here is perfectly reasonable.
In C++17, as of P0137, this changes a lot. Now, [basic.compound] defines pointers as:
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 (5.7), or
— the null pointer value (4.11) for that type, or
— an invalid pointer value.
So now, past
is a value of the 2nd type (a pointer past the end of), but val
is a value of the 1st type (a pointer to). Those are different categories of values and are not comparable:
A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory (1.7) occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively. [ Note: A pointer past the end of an object (5.7) is not considered to point to an unrelated object of the object’s type that might be located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see 3.7. —end note ]
past
doesn't point to something, so viewing its contents as if it were the same as val
is no longer meaningful.
What I really want to understand is: what does "p points to object x" means.
The object p
contains a value that corresponds to the location of the object x
in memory.
That's it. That's all it means. You seem determined to make this more complicated than it needs to be.
Pointer types are not arithmetic types, and aren't meant to be arbitrarily munged like that. Valid pointer values are obtained by using the unary &
operator on an lvalue, using an array expression that isn't the operand of the sizeof
or unary &
operator, or calling a library function that returns a pointer value.
Everything beyond that (size, representation, physical vs. virtual, etc.) is an implementation detail, and implementations vary widely when it comes to representing addresses. That's why the standards don't say anything about what to expect when you play Dr. Frankenstein with pointer values.
If you are intimately familiar with your platform's addressing conventions (both virtual and physical), and you know how your implementation lays out items in memory and how it represents pointer types, and you have a valid use case for hacking your pointer values this way, then hack away to your heart's content - neither language standard has anything to say on the subject.