Это объявление
int arr[][2] = { {1}, 2, 3};
объявляет массив из двух элементов типа int[2]
.
Это выражение
(**arr)
дает целочисленное значение 1.
Это объявление
int (*ptr)[2] = arr + 1;
объявляет указатель на второй элемент массива обр. Так что * ptr возвращает эту вторую «строку» массива arr. Используя в таких выражениях
(**arr)[*ptr]
, он преобразуется в указатель на свой первый элемент.
Итак, у вас есть выражение вроде
int[int *]
или
i[p]
, где i - целочисленное значение, а p - указатель.
Это эквивалентно
int *[int]
или
p[i]
, поскольку согласно C ++ Standard (или C Standard) оба оцениваются как
*( p + i )
Так как ** arr равен 1, а выражение * ptr указывает на первый элемент второй строки, а затем на результат является вторым элементом второй строки, равным 3.
Из стандарта C ++ 17 (5.2.1 подписка)
1 Постфиксное выражение, за которым следует выражение в квадратных скобках: постфиксное выражение. Одно из выражений должно иметь тип «массив из T» или «указатель на T», а другое должно иметь перечисление с незаданной областью или целочисленный тип. Результат имеет тип «T». Тип «T» должен быть полностью определенным типом объекта.64 Выражение E1 [E2] идентично (по определению) * ((E1) + (E2)) [Примечание: см. 5.3 и 5.7 для деталей * и + и 8.3.4 для деталей массивов. - примечание конца], за исключением того, что в случае операнда массива, результатом является lvalue, если этот операнд является lvalue и xvalue в противном случае.
То есть, если у вас есть такой массив
T a[N];
где T
- это некоторый спецификатор типа, когда выражение
a[i]
эквивалентно
i[a]
при условии, что i
представляет выражение постфикса.
Вот демонстрационная программа.
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t i = 0;
while ( i != N ) std::cout << i++[a] << ' ';
std::cout << '\n';
return 0;
}
Его вывод
1 2 3 4 5