С++ array [index] vs index [array]

Возможный дубликат:
В массивах C почему это так? a [5] == 5 [a]

Является ли возможность как массива [index], так и index [array] функцией компилятора или языковой функцией. Как можно сделать второй?

Ответ 1

Компилятор превратит

index[array]

в

*(index + array)

При нормальном синтаксисе он превратит

array[index]

в

*(array + index)

и, следовательно, вы видите, что оба выражения оцениваются с одинаковым значением. Это выполняется как для C, так и для С++.

Ответ 2

С самых ранних дней C выражение a[i] было просто адресом [0], добавленным в я (увеличенным размером a [0]), а затем де-ссылкой. Фактически все они были эквивалентными:

a[i]
i[a]
*(a+i)

====

Единственное, что меня беспокоит, это фактическая де-ссылка. В то время как все они производят один и тот же адрес, удаление ссылок может быть проблемой, если типы a и i различны.

Например:

    int i = 4;
    long a[9];
    long x = a[i]; //get the long at memory location X.
    long x = i[a]; //get the int at memory location X?

Я действительно не тестировал это поведение, но это то, что вы, возможно, захотите наблюдать. Если он изменяет то, что получает де-ссылку, он может вызвать всевозможные проблемы с массивами объектов.

====

Update:

Возможно, вы можете смело игнорировать бит выше между строками =====. Я тестировал его под Cygwin с коротким и длинным, и все выглядит хорошо, поэтому, я думаю, мои страхи были необоснованными, по крайней мере, для основных случаев. Я до сих пор не знаю, что происходит с более сложными, потому что это не то, что я когда-либо захочу сделать.

Ответ 3

Как говорит Мэтью Уилсон в Imperfect С++, это можно использовать для обеспечения безопасности типов на С++, предотвращая использование DIMENSION_OF() - как макросы с экземплярами типов, которые определяют оператор индекса, как в:

#define DIMENSION_OF_UNSAFE(x)  (sizeof(x) / sizeof((x)[0]))

#define DIMENSION_OF_SAFER(x)  (sizeof(x) / sizeof(0[(x)]))

int ints[4];

DIMENSION_OF_UNSAFE(ints); // 4
DIMENSION_OF_SAFER(ints); // 4

std::vector v(4);

DIMENSION_OF_UNSAFE(v); // gives impl-defined value; v likely wrong
DIMENSION_OF_SAFER(v); // does not compile

Там больше для решения указателей, но для этого требуются дополнительные шаблонные шаблоны. Ознакомьтесь с реализацией STLSOFT_NUM_ELEMENTS() в библиотеках STLSoft и прочитайте все это в главе 14 Imperfect С++.

edit: некоторые из комментаторов предполагают, что реализация не отменяет указатели. Он (как и пользовательские типы), как показано в следующей программе. Вы можете проверить это с помощью несвязанных строк 16 и 18. (Я просто сделал это на Mac/GCC4 и отклонил обе формы).

1
2 #include <stlsoft/stlsoft.h>
3
4 #include <vector>
5
6 #include <stdio.h>
7
8 int main()
9 {
10         int     ar[1];
11         int*    p = ar;
12         std::vector<int>        v(1);
13
14         printf("ar: %lu\n", STLSOFT_NUM_ELEMENTS(ar));
15
16 //      printf("p: %lu\n", STLSOFT_NUM_ELEMENTS(p));
17
18 //      printf("v: %lu\n", STLSOFT_NUM_ELEMENTS(v));
19
20         return 0;
21 }
22

Ответ 4

В C и С++ (с массивом, являющимся указателем или массивом) это языковая функция: арифметика указателя. Операция a [b], где либо a, либо b является указателем, преобразуется в арифметику указателя: * (a + b). С добавлением, являющимся симметричным, переупорядочение не меняет смысла.

Теперь существуют различия для не указателей. Фактически, заданный тип A с перегруженным оператором [], тогда [4] является действительным вызовом метода (вызовет оператор A::), но противоположное даже не будет компилироваться.