Pointer arithmeti c - как компилятор определяет количество байтов для увеличения? - PullRequest
3 голосов
/ 09 мая 2020

Рассмотрим следующий фрагмент кода.

#include <iostream>

int main(){
  int a[] = {1,2,3,4,5};
  int b = 5;
  std::cout << a[b] << std::endl;
  std::cout << b[a] << std::endl;
}

Я понимаю, что a[b] и b[a] идентичны, как указано в стандарте:

За исключением случаев, когда он был объявлен для класса (13.5.5 ), оператор индекса [] интерпретируется таким образом, что E1 [E2] идентично * ((E1) + (E2)). Из-за правил преобразования, которые применяются к +, если E1 - это массив, а E2 - целое число, то E1 [E2] относится к E2-му члену E1. Поэтому, несмотря на его асимметричный вид c, индексирование - это коммутативная операция.

Однако я все еще не совсем понимаю. Компилятор адресует арифметику c в байтах. Поскольку int занимает 4 байта, и a[b], и b[a] преобразуются в *(a + b * 4). У меня вопрос: как компилятор определяет, что правильный перевод *(a + b * 4) вместо *(b + a * 4)? Когда компилятору дается выражение в форме E1[E2], компилятор может преобразовать его либо в *(E1 + E2 * 4), либо в *(E2 + E1 * 4) - как компилятор узнает, какое из них правильное?

Ответы [ 2 ]

4 голосов
/ 09 мая 2020

Это не размер объекта, который является определяющим типом. Это фактический полный тип объекта.

Компилятор знает фактический тип каждого объекта. Компилятор знает не только, что a - это четыре байта (или восемь байтов в 64-битной системе), но это указатель, а b - это целочисленный тип. Это фундаментальный аспект C ++: тип каждого объекта известен и должен быть известен во время компиляции.

Итак, когда тип указателя добавляется к целочисленному типу, целочисленное значение умножается на размер типа, на который указывает. Не имеет значения, какой из них находится слева и справа от оператора +. Если один операнд является указателем, а другой - целочисленным типом, это то, что происходит в C ++.

0 голосов
/ 09 мая 2020

Представьте себе язык C ± ±, который похож на C ++, за исключением того, что в нем нет понятия индексации массива и индекса operator []. Однако все остальные правила и определения C ++ по-прежнему применяются.

За исключением случаев, когда он был объявлен для класса (13.5.5), оператор индекса [] интерпретируется таким образом, что E1 [E2] идентично * ((E1) + (E2)).

То, что здесь говорится в стандарте C ++, можно примерно прочитать так: компилятор C ++ сначала переводит все выражения нижнего индекса E1[E2] в *((E1)+(E2)). Результатом является действительный код C ± ±, который затем оценивается в соответствии с правилами C ± ±.

Это означает, что a[b] и b[a] преобразуются в *(a + b) и *(b + a) соответственно. , которые идентичны, поскольку сложение коммутативно в C ++ (и, следовательно, C ± ±).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...