-1

As far as I understand, pointer arithmetic is defined mainly in expr.add. But it seems defined only for static arrays, not dynamic ones:

4 When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
(4.1) — If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
(4.2) — Otherwise, if P points to an array element i of an array object x with n elements (9.3.3.4),76 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.
(4.3) — Otherwise, the behavior is undefined.

Basically it states that if you have a pointer to an object within an array, you can reach all other arrays elements (and define the location of one-past-last element) through pointer arithmetic. But regarding array definition, it links to dcl.array that seems to define only arrays declared through T arr[constant expression] this constant expression possibly empty.

I don't see arrays declared, for instance, with T* arr = ::new T[runtime unsigned integral expression].

Obviously pointer arithmetic is expected to behave in the same way for dynamic arrays but, out of pure curiosity, how is it defined in the standard?

4
  • 2
    There's nothing in the text you have quoted restricting the definition to apply to static arrays. Also T *arr = ::new T[whatever] does not declare an array. It defines [a definition is a type of declaration] a pointer arr, and initialises it with the result of a new expression. That new expression dynamically allocates an array, and gives a result equal to the address of the first element of that dynamically allocated array. Point is - it is possible to allocate an array statically, dynamically, or (third possibility) automatically. Commented Jul 18 at 11:53
  • Dynamically allocated arrays also start from a pointer in memory, all pointer arithmetic is the same. But then there is also arrays on the stack etc. Commented Jul 18 at 13:27
  • 3
    I'd say cross-references (or their absence) bear no normative meaning, they exist for convenience. The wording says an array object x with n elements, this apply to array objects irrespective of their way of creation. [expr.new] can create array objects (timsong-cpp.github.io/cppwp/n4861/expr.new#1.sentence-1 etc.) Commented Jul 18 at 14:03
  • 1
    T* arr is no array. I points to one. And the type of that array is T[runtime unsigned integral expression]. Such an array is declared via T arr[constant expression]. Commented Jul 18 at 19:48

2 Answers 2

1

It seems the logical mistake you're making is in assuming that dcl.array is the only way in which you can create an array object. As you figured out, there are more ways to create one. dcl.array specifically is how you define an array variable or member, but not all arrays are variables or members.

Sign up to request clarification or add additional context in comments.

10 Comments

Hi, I agree but [expr.add] only references [decl.arr] it seems?
@Oersted • and [dcl.array] references [expr.new], and [expr.new] explains dynamic allocation of arrays.
I saw timsong-cpp.github.io/cppwp/n4861/dcl.array#7 but it deals with unbound arrays whose size is determined, at compile-time, from the number of initializers. I'm failing to relate it to a runtime-sized array declaration.
But have you seen [expr.new]?
@Oersted An array form of new expression can accept a size determined at run time. It is not possible in standard C++ to declare T arr[n] where n is not a compile time constant (some C++ compilers support this as a non-standard extension, for compatibility with C (after C99).
Hi, from timsong-cpp.github.io/cppwp/n4861/dcl.array#7 "An array bound may also be omitted when an object (but not a non-static data member) of array type is initialized and the declarator is followed by an initializer ([dcl.init], [class.mem], [expr.type.conv], [expr.new]). In these cases, the array bound is calculated from the number of initial elements (say, N) supplied ([dcl.init.aggr]), and the type of the array is “array of N U”." It does not correspond to T* arr = ::new T[n]?
I think it covers this kind of declaration only: int* p = ::new int[]{ 1,2,3 };
@Eljay: I think the relevant comment is from Language-Lawyer. The [decl.array] has no "normative meaning", thus any created array apply, even those created by [expr.new] as T* p = ::new T[n];
He said the cross reference itself has no normative meaning. That does not mean that what is cross referenced to does not have normative meaning.
It's what I understood. Sorry if it was unclear. In this context I understand it as "all kind of arrays are concerned, for instance those declared as in [decl.array]". By the way, I find it more confusing than helpful (at least it confused me ;) ).
0

The issue actually lies in how I am interpretating the standard wording. In fact, it applies to any array, whatever the way it is created. As commented by Language-Lawyer, I should consider the reference to [decl.array] as a mere example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.