*(&arr + 1) может быть записано как (&arr)[1] или как 1[&arr]. Именно в таком "более интересном" виде этот вопрос периодически всплывает в обсуждениях.
В С++ формального ответа на этот вопрос не существует. Тема когда-то активно обсуждалась, но так и застряла в состоянии "drafting":
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
Никаких поползновений дать окончательный ответ на этот вопрос пока не видно. То есть до сих пор в языке С++ нет ответа на давний вопрос о том, можно ли делать так
int arr[10];
for (int *p = &arr[0]; p != &arr[10]; ++p) // `&arr[10]` - UB или нет?
...;
for (int *p = arr; p != 1[&arr]; ++p) // `1[&arr]` - UB или нет?
...;
Вопрос о формальной легальности по крайней мере первого варианта известен еще со времен Царя Гороха, но вменяемого ответа на него до сих пор не предоставили.
В языке С предприняли попытки разрешить часть таких ситуаций, объявив соседние операторы & и * "аннигилирующими" друг друга еще до начала вычисления выражения. Это легализовало вариант &arr[10]
&arr[10] <=> &*(arr + 10) <=> arr + 10 - нет UB
Но это формально не легализовало вариант 1[&arr] (ваш вариант). В этом варианте мы имеем
(int *) *(&arr + 1)
^ ^^^^^^^^^^^
| выражение, результат которого имеет тип `int [10]`
|
стандартное неявное преобразование массива к указателю
Точно так же, как язык С объявил соседние & и * "аннигилирующими" друг друга, надо было бы соседнее "неявное преобразование массива к указателю" и оператор * объявить "коллапсирующим" до просто преобразования указателя, т.е. считать это выражение эквивалентным
(int *) (&arr + 1)
Однако этого пока сделано не было. То есть в языке С ваш вариант формально порождает неопределенное поведение.
В языке С++ все пока (и уже давно) подвешено в воздухе.
std::extent_vдля этих целей. – HolyBlackCat Dec 23 '18 at 21:08&- одна из немногих вещей (как иsizeof), которая не превращает массив в указатель на его первый элемент. Так что он с массивами работает так же, как и с остальными типами. "Это определено стандартом?" Конечно. – HolyBlackCat Dec 23 '18 at 21:14arrэто массив, а не указатель на первый элемент (хотя массив может неявно преобразовываться в указатель на первый элемент) – user7860670 Dec 23 '18 at 21:14*arrэквивалентно*static_cast<int *>(arr)Если быarrбыл указателем на первый элемент, то&arrдал бы вам указатель на указатель на первый элемент, а не указатель на массив. И да, разыменовывание*(&arr + 1)будет неопределенным поведением, так как указатель&arr + 1не указывает на валидный объект. – user7860670 Dec 23 '18 at 21:17&иsizeofи еще в кое-каких редких случаях. – HolyBlackCat Dec 23 '18 at 21:18*к невалидному указателю. Вstd::end(arr)нет такого применения. В рассматриваемом выражении - есть. Об этом и речь. – AnT stands with Russia Dec 23 '18 at 22:47