Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

T* versus char* pointer arithmetic

Assume we have an array that contains N elements of type T.

T a[N];

According to the C++14 Standard, under which conditions do we have a guarantee that

 (char*)(void*)&a[0] + n*sizeof(T) == (char*)(void*)&a[n],  (0<=n<N) ?

While this is true for many types and implementations, the standard mentions it in a footnote, and in an ambiguous way:

§5.7.6, footnote 85) Another way to approach pointer arithmetic ...

There is little indication that this other way was thought of being equivalent to the standard's way. It might rather be a hint for implementers that suggests one of many conforming implementations.


Edits:

People have underestimated the difficulty of this question.

This question is not about what you can read in textbooks, it is about what what you can deduce from the C++14 Standard through the use of logic and reason.

If you use 'contiguous' or 'contiguously', please also say what is being contiguous.

While T[] and T* are closely related, they are abstractions, and the addition on T* x N may be defined by the implementation in any consistent way.

The equation was rearranged using pointer addition. If p points to a char, p+1 is always defined using (§5.7 (4)) or unary addition, so we don't run into UB. The original included a pointer subtraction, which might have caused UB early on. (The char pointers are only compared, not dereferenced).

like image 992
Heiko Bloch Avatar asked Oct 05 '16 15:10

Heiko Bloch


2 Answers

In [dcl.array]:

An object of array type contains a contiguously allocated non-empty set of N subobjects of type T.

Contiguous implies that the offset between any consecutive subobjects of type T is sizeof(T), which implies that the offset of the nth subobject is n*sizeof(T).

The upper bound of n < N comes from [expr.add]:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 <= i + j < n; otherwise, the behavior is undefined.

like image 151
Barry Avatar answered Oct 08 '22 22:10

Barry


It's always true, but instead of looking at the rules for pointer arithmetic you must rely on the semantics given for the sizeof operator (5.3.3 [expr.sizeof]):

When applied to a reference or a reference type, the result is the size of the referenced type. When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array. The size of a most derived class shall be greater than zero. The result of applying sizeof to a base class subobject is the size of the base class type. When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.

It should be clear that there's only one packing that puts n non-overlapping elements in space of n * sizeof(element), namely that they are regularly spaced sizeof (element) bytes apart. And only one ordering is allowed by the pointer comparison rules found under the relational operator section (5.9 [expr.rel]):

Comparing pointers to objects is defined as follows:

  • If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript compares greater.
like image 41
Ben Voigt Avatar answered Oct 09 '22 00:10

Ben Voigt