If you look at the expression p[1]
, p
is a Base*
(Base
is a completely-defined type) and 1
is an int
, so according to ISO/IEC 14882:2003 5.2.1 [expr.sub] this expression is valid and identical to *((p)+(1))
.
From 5.7 [expr.add] / 5, when an integer is added to a pointer, the result is only well defined when the pointer points to an element of an array object and the result of the pointer arithmetic also points the an element of that array object or one past the end of the array. p
, however, does not point to an element of an array object, it points at the base class sub-object of a Derived
object. It is the Derived
object that is an array member, not the Base
sub-object.
Note that under 5.7 / 4, for the purposes of the addition operator, the Base
sub-object can be treated as an array of size one, so technically you can form the address p + 1
, but as a “one past the last element” pointer, it doesn’t point at a Base
object and attempting to read from or write to it will cause undefined behavior.