странный синтаксис

295
04 апреля 2017, 12:35

очень неясно как работает данный код

int a[] = {4, 5, 2, 3, 1};
int i = *a;
for (;i;)
{
    std::cout << i--[a];  // не понятная строчка
}
//  output: 1325

к чему тут декремент применяется???

ну, очевидно, что к переменной i, раз цикл завершается.

Но как тогда происходят обращения к элементам массива ? почему нет ошибки компиляции ?

Впервый раз в жизни встречаю подобный код

Answer 1

Декремент тут применяется 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).

Answer 2

Оператор индексирования относится к классу постфиксных операторов. Он определяется следующим образом (стандарт 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
READ ALSO
Не открывается окошко QQuickView в проекте

Не открывается окошко QQuickView в проекте

Если запускаю проект из Qt Creator, все работает нормальноНо если пытаюсь сделать сборку, то окошко с qml не открывается

307
Поиск элемента в QSqlTableModel

Поиск элемента в QSqlTableModel

Есть QSqlTableModel, связанная с таблицей в базе данныхНужно найти элемент(получить его индекс), находящийся в столбце "column" и для которого значение...

199
Решение олимпиадной задачи подсуммы

Решение олимпиадной задачи подсуммы

Вообщем есть последовательность чисел

267