Let's consider this code:
int i;
int is[10]{};
unsigned char * p = reinterpret_cast<unsigned char*>(&i);
//p defined to point to the object-representation of the first element of array ints
unsigned char * ps = reinterpret_cast<unsigned char*>(&is[0]);
p += sizeof(int);
ps += sizeof(int);
//now ps points to the end of ints[0] and p point to the end of i;
p += sizeof(int); //Undefined behavior according to [expr.add]
ps += sizeof(int); //Undefined behavior?
unsigned char c = *ps;//Undefined behavior?
If we consider that ps
points to the object-representation of is[0]
then according to pointer arithmetic rule, the behavior is undefined at the two last code line.
Nevertheless, if ps
is also a pointer to the object-representation of the array of int is
the behavior is defined.
So my question is: does a pointer to the object-representation of a suboject is also a pointer to an element of the object-representation of the containing complete object?
General case
Yes, the pointer to the object-representation of a suboject is also a pointer to a part of the object-representation of the containing complete object.
This can be deduced from:
1.8/1: An object is a region of storage.
3.9/4: The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T).
5.3.3/1: The sizeof operator yields the number of bytes in the object representation of its operand.
1.8/2: Objects can contain other objects, called subobjects. A subobject can be a member subobject, a base class subobject, or an array element. An object that is not a subobject of any other object is called a complete object.
The fact that an object is a region of storage and that the subobject is contained within the region of storage means that the suboject representation is contained in the object representation.
As explained in this other answer, the pointer to the object representation is in fact the pointer to the object.
Specific case of the array
Yes, the pointer to the object representation of a subobject (i.e. in this case an array element) is a pointer to an element of the object-representation of the containing complete object (i.e. in this case the array).
8.4.3/1: (...) An object of array type contains a contiguously allocated non-empty set of N subobjects of type T. (...)
So by definition:
the elements of the array are contiguously allocated, meaning that there is no empty space between the elements.
the object representation of each element is a sequence of sizeof(T) unsigned chars, and the object representation of the complete array is the resulting N*sizeof(T) unsigned chars.
We can then deduce:
As explained in this other answer, the pointer to the object representation is in fact the pointer to the object.
the address of the k-th element in the array corresponds to the k-th element in the object representation of the array, and is by construction at an offset of k*sizeof(T) unsigned chars of the address of the array representation.
So the last 2 statements of your code are not undefined behavior, as long as you remain within the boundaries of is
There's no such thing as a "pointer to the object representation". You have a pointer which holds the object's address, and that pointer can be derived safely or unsafely.
The "object representation" comes into play when you read within the object's address range using an lvalue of narrow character type, not when the pointer is formed or converted.
Nothing in the rules for reinterpret_cast<unsigned char*>(p)
says anything about the result being some special "pointer to object representation". It's still just another alias for the same object.
来源:https://stackoverflow.com/questions/46738487/can-one-get-a-pointer-to-a-complete-object-representation-element-from-a-pointer