Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is incrementing a pointer to a 0-sized dynamic array undefined?

AFAIK, although we cannot create a 0-sized static-memory array, but we can do it with dynamic ones:

int a[0]{}; // Compile-time error int* p = new int[0]; // Is well-defined 

As I've read, p acts like one-past-end element. I can print the address that p points to.

if(p)     cout << p << endl; 
  • Although I am sure of we cannot dereference that pointer (past-last-element) as we cannot with iterators (past-last element), but what I am not sure of is whether incrementing that pointer p? Is an undefined behaviour (UB) like with iterators?

    p++; // UB? 
like image 672
Itachi Uchiwa Avatar asked Nov 03 '19 21:11

Itachi Uchiwa


People also ask

Can you increment an array pointer?

Pointers are also useful while working with arrays, because we can use the pointer instead of an index of the array. A pointer can be incremented by value or by address based on the pointer data type.

Can you increment an array?

No, it's not OK to increment an array. Although arrays are freely convertible to pointers, they are not pointers. Therefore, writing a++ will trigger an error.

Can we increment int pointer?

When a pointer is incremented, it actually increments by the number equal to the size of the data type for which it is a pointer. For Example: If an integer pointer that stores address 1000 is incremented, then it will increment by 2(size of an int) and the new address it will points to 1002.

Are dynamic arrays pointers?

A dynamically allocated array is declared as a pointer, and must not use the fixed array size declaration. The above declaration creates a pointer, but doesn't yet allocate any memory to it.


2 Answers

Pointers to elements of arrays are allowed to point to a valid element, or one past the end. If you increment a pointer in a way that goes more than one past the end, the behavior is undefined.

For your 0-sized array, p is already pointing one past the end, so incrementing it is not allowed.

See C++17 8.7/4 regarding the + operator (++ has the same restrictions):

f 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 137
interjay Avatar answered Oct 03 '22 15:10

interjay


I guess you've already have the answer; If you look a bit deeper: You've said that incrementing an off-the-end iterator is UB thus: This answer is in what is an iterator?

The iterator is just an object that has a pointer and incrementing that iterator is really incrementing the pointer it has. Thus in many aspects an iterator is handled in terms of a pointer.

int arr[] = {0,1,2,3,4,5,6,7,8,9};

int *p = arr; // p points to the first element in arr

++p; // p points to arr[1]

Just as we can use iterators to traverse the elements in a vector, we can use pointers to traverse the elements in an array. Of course, to do so, we need to obtain pointers to the first and one past the last element. As we’ve just seen, we can obtain a pointer to the first element by using the array itself or by taking the address-of the first element. We can obtain an off-the-end pointer by using another special property of arrays. We can take the address of the nonexistent element one past the last element of an array:

int *e = &arr[10]; // pointer just past the last element in arr

Here we used the subscript operator to index a nonexisting element; arr has ten elements, so the last element in arr is at index position 9. The only thing we can do with this element is take its address, which we do to initialize e. Like an off-the-end iterator (§ 3.4.1, p. 106), an off-the-end pointer does not point to an element. As a result, we may not dereference or increment an off-the-end pointer.

This is from C++ primer 5 edition by Lipmann.

So it is UB don't do it.

like image 37
Raindrop7 Avatar answered Oct 03 '22 14:10

Raindrop7