очень неясно как работает данный код
int a[] = {4, 5, 2, 3, 1};
int i = *a;
for (;i;)
{
std::cout << i--[a]; // не понятная строчка
}
// output: 1325
к чему тут декремент применяется???
ну, очевидно, что к переменной i
, раз цикл завершается.
Но как тогда происходят обращения к элементам массива ? почему нет ошибки компиляции ?
Впервый раз в жизни встречаю подобный код
Декремент тут применяется i
хотя бы просто потому, что больше он в данной записи ни к чему применяться не может - справа от него стоит лексема [
, которая началом выражения-операнда быть никак не может.
Тема же эквивалентности a[i]
и i[a]
заезжена донельзя. Выражение x[y]
по определению является лишь сокращенной формой записи для *(x + y)
. Один операнд должен быть массивом/указателем, а другой - целочисленным или enum значением. Причем ограничений на порядок указания операндов не накладывается. Поэтому ваше i--[a]
эквивалентно *(i-- + a)
эквивалентно *(a + i--)
и эквивалентно a[i--]
. Никакой "ошибки компиляции" тут нет.
Вышесказанное относится именно и только к встроенному оператору []
. Для перегруженного оператора []
порядок аргументов фиксирован, то есть для выражения x[y]
будет рассматриваться только перегруженный вариант x.operator[](y)
, но не y.operator[](x)
.
Оператор индексирования относится к классу постфиксных операторов. Он определяется следующим образом (стандарт C++, раздел 5.2.1 Subscripting)
1 A postfix expression followed by an expression in square brackets is a postfix expression.
То есть за постфиксным выражением следует выражение в квадратных скобках.
В этом выражении
i--[a]
i--
- это оператор пост-декремента, который относится к классу постфиксных выражений. Итак, имеется
i-- [a]
| |
постфиксное выражение выражение в квадратных скобках
Так что с точки зрения синтаксиса данное выражение совершенно корректное.
Далее в той же самой цитате из стандарта имеется продолжение
1 ... One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration or integral type. The result is of type “T.” The type “T” shall be a completely-defined object type.64 The expression E1[E2] is identical (by definition) to *((E1)+(E2))
из которого следует, что одно из выражений должно быть либо массивом, либо указателем, а другое выражение - перечислением или целочисленным типом. Какое из этих двух выражений какой должен иметь тип не существенно, так как по определению выражение E1[E2]
эквивалентно выражению *((E1) + (E2))
.
В С++ вы можете написать даже более вычурную конструкцию, добавив знак плюс перед именем массива. Например,
#include <iostream>
int main()
{
int a[] = { 0, 2, 4, 6, 8 };
int i = 0;
std::cout << i++[+a] << std::endl;
return 0;
}
В C такая конструкция i++[+a]
не будет компилироваться, так как в C в отличии от C++ нельзя применять унарный плюс к имени массива.
В C++ пользователь также может перегружать оператор индексирования для списка инициализации в фигурных скобках. Например,
#include <iostream>
#include <initializer_list>
#include <numeric>
int main()
{
struct A
{
long long int operator []( std::initializer_list<int> l ) const
{
return std::accumulate( l.begin(), l.end(), 0ll );
}
};
std::cout << A()[{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }] << std::endl;
return 0;
}
Вывод программы на консоль
55
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Если запускаю проект из Qt Creator, все работает нормальноНо если пытаюсь сделать сборку, то окошко с qml не открывается
Есть QSqlTableModel, связанная с таблицей в базе данныхНужно найти элемент(получить его индекс), находящийся в столбце "column" и для которого значение...