Ответ 1
-2[arr]
анализируется как -(2[arr])
. В C (и в С++, игнорируя перегрузку), определение X[Y]
равно *(X+Y)
(подробнее об этом см. В этот вопрос), что означает, что 2[arr]
равно arr[2]
.
#include <iostream>
using namespace std;
int main()
{
int arr[3] = { 10, 20, 30 };
cout << arr[-2] << endl;
cout << -2[arr] << endl;
return 0;
}
Вывод:
4196160
-30
Здесь arr[-2]
находится вне допустимого диапазона и недействителен, вызывая поведение undefined.
Но -2[arr]
оценивается как -30
. Почему?
Не arr[-2]
эквивалентно -2[arr]
?
-2[arr]
анализируется как -(2[arr])
. В C (и в С++, игнорируя перегрузку), определение X[Y]
равно *(X+Y)
(подробнее об этом см. В этот вопрос), что означает, что 2[arr]
равно arr[2]
.
Компилятор анализирует это выражение
-2
как
unary_minus decimal_integer_literal
То есть определения целых литералов не содержат признаков.
В свою очередь выражение
2[arr]
анализируется компилятором как постфиксное выражение.
Постфиксные выражения имеют более высокий приоритет, чем унарные выражения. Таким образом, это выражение
-2[arr]
эквивалентно
- ( 2[arr] )
Таким образом, унарный минус применяется к lvalue, возвращаемому выражением postfix 2[arr]
.
С другой стороны, если вы написали
int n = -2;
а затем
n[arr]
то это выражение будет эквивалентно
arr[-2]
-2[arr]
эквивалентен -(2[arr])
, что эквивалентно -arr[2]
. Однако (-2)[arr]
эквивалентно arr[-2]
.
Это связано с тем, что E1 [E2] идентичен (* ((E1) + (E2)))
Основная проблема заключается в приоритете оператора. В С++ []
, т.е. Оператор Subscript имеет больше приоритетов (несколько схожий с предпочтением), чем оператор -
unary_minus.
Поэтому, когда вы пишете,
arr[-2]
Сначала выполняется компилятор arr[]
, затем -
, но unary_minus заключен в пределах [-2]
, поэтому выражение разлагается вместе.
В <
-2[arr]
То же самое происходит, но компилятор выполняет 2[]
сначала оператор -
, поэтому он заканчивается тем, что
-(2[arr])
не (-2)[arr]
Ваше понимание концепции, что,
arr[i]
i[arr]
и *(i+arr)
все одинаковы. Это все эквивалентные выражения.
Если вы хотите написать таким образом, напишите его как (-2)[arr]
. Вы получите то же самое значение точно.
Отметьте это для будущего обращения: http://en.cppreference.com/w/cpp/language/operator_precedence