2014-10-07 1 views
7

Я читаю книгу Кочана «Программирование на C». В разделе «Указатель и массивы» на с. 264 он говорит:Почему цикл по массиву с использованием индексации массивов медленнее, чем для доступа к указателю?

В общем, процесс индексации массива занимает больше времени для выполнения, чем делает процесс доступа к содержимому указателя. На самом деле, это одна из основных причин, почему указатели используются для доступа к элементам массива - генерируемый код обычно более эффективен. Конечно, если доступ к массиву обычно не последователен, то указатели ничего не выполняют, поскольку это проблема, поскольку выражение * (указатель + j) занимает столько же времени, сколько и массив выражений [j] ,

Может кто-нибудь объяснить, что быстрее, чем что? В частности, если скорость массива [j] = скорость * (указатель + j), то что такое процесс индексации массива и что такое процесс доступа к содержимому указателя? Кроме того, есть вопросы и ответы на SO, в которых упоминается, что массив [j] преобразуется в * (массив + j) во время компиляции, поэтому не должно быть никакой разницы.

Основная информация: Пожалуйста, дайте мне очень простой пример того, что говорит Кочан. 2 фрагмента кода и указать быстрее, не нужно объяснять, почему это правда.

+3

С какого года эта книга? – 2501

+1

Я думаю, что то, что говорит Кочан, заключается в том, что приращение указателя размером элемента быстрее, чем умножение индекса на размер элемента и добавление его к базовому адресу. Это один из тех случаев, когда разница достаточно мала, что это, вероятно, не имеет значения, и если вы работаете на уровне, где это действительно имеет значение, вы, вероятно, уже хорошо знаете разницу. – Caleb

+0

http://stackoverflow.com/questions/4534617/lea-instruction – 2501

ответ

5

Посмотрите на сниппета

int arr[5] = {0}; 
int *p = arr; 
int c = 1; 

Теперь увидеть петлю 1:

for(int i = 0; i < 5; i++) 
    arr[i] = c++ + 1; 

петля 2:

for(int i = 0; i < 5; i++) 
    *p++ = c++ + 1; 

Разница между этими двумя петлями является их тело. Первый цикл содержит arr[i] = c++ + 1. Это эквивалентно *(arr + i) = c++ + 1. Что это значит от *(arr + i)?
Это означает, что:

  • Fetch базовый адрес указателя.
  • Извлечь значение i
  • Добавить значение i на базовый адрес.
  • Выделить окончательный адрес.

В то время как в случае тела *p++ средств второго контура в:

  • Извлекает значение p
  • разыменовать адреса перед его приращением.
  • Увеличьте адрес на 1.

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

+1

Я предполагаю, что вы имели в виду 'int * p = arr;' –

+0

@MaciejSzpakowski; К сожалению! Это была опечатка. – haccks

+0

@Downvoter, позаботьтесь, чтобы объяснить? – haccks