Возможный дубликат:
В массивах C почему это так? a [5] == 5 [a]
Является ли возможность как массива [index], так и index [array] функцией компилятора или языковой функцией. Как можно сделать второй?
Возможный дубликат:
В массивах C почему это так? a [5] == 5 [a]
Является ли возможность как массива [index], так и index [array] функцией компилятора или языковой функцией. Как можно сделать второй?
Компилятор превратит
index[array]
в
*(index + array)
При нормальном синтаксисе он превратит
array[index]
в
*(array + index)
и, следовательно, вы видите, что оба выражения оцениваются с одинаковым значением. Это выполняется как для C, так и для С++.
С самых ранних дней 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 с коротким и длинным, и все выглядит хорошо, поэтому, я думаю, мои страхи были необоснованными, по крайней мере, для основных случаев. Я до сих пор не знаю, что происходит с более сложными, потому что это не то, что я когда-либо захочу сделать.
Как говорит Мэтью Уилсон в 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
В C и С++ (с массивом, являющимся указателем или массивом) это языковая функция: арифметика указателя. Операция a [b], где либо a, либо b является указателем, преобразуется в арифметику указателя: * (a + b). С добавлением, являющимся симметричным, переупорядочение не меняет смысла.
Теперь существуют различия для не указателей. Фактически, заданный тип A с перегруженным оператором [], тогда [4] является действительным вызовом метода (вызовет оператор A::), но противоположное даже не будет компилироваться.