For addition, either both operands shall have arithmetic
type, or one operand shall be a pointer to a completely-defined object
type and the other shall have integral type.
Otherwise, if P points to a (possibly-hypothetical) array element i
of an array object x with n elements ([dcl.array]),65
the expressions P + J and J + P
(where J has the value j)
point to the (possibly-hypothetical) array element
i+j of x if 0≤i+j≤n
and the expression P - J
points to the (possibly-hypothetical) array element
i−j of x if 0≤i−j≤n.
When two pointer expressions P and Q are subtracted,
the type of the result is an implementation-defined signed
integral type; this type shall be the same type that is defined as
std::ptrdiff_t in the <cstddef>
header ([support.types.layout]).
For addition or subtraction, if the expressions P or Q have
type “pointer to cvT”, where T and the array element type
are not similar, the behavior is undefined.
[Example 1: int arr[5]={1, 2, 3, 4, 5};
unsignedint*p =reinterpret_cast<unsignedint*>(arr +1);
unsignedint k =*p; // OK, value of k is 2 ([conv.lval])unsignedint*q = p +1; // undefined behavior: p points to an int, not an unsigned int object — end example]
As specified in [basic.compound],
an object that is not an array element
is considered to belong to a single-element array for this purpose and
a pointer past the last element of an array of n elements
is considered to be equivalent to a pointer to a hypothetical array element
n for this purpose.