Использование индексов

Рассмотрим сначала обычный вариант организации цикла без явного использования указателей. Пусть функция обрабатывает одномерный статический или динамический массив ar размерности size.

int MySum0 (int* ar, unsigned size)

{ int S=0;

for (unsigned i=0; i<size; i++) S+=ar[i]; // или S+=i[ar];

return S;

}

При использовании индексного выражения компилятор преобразует его в адресное *(ar+i). При выполнении программы сначала вычисляется адрес ar+i так, как было описано раньше, а затем берётся содержимое по этому адресу. При этом важно обратить внимание на то, что такое преобразование выполняется не потому, что в заголовке функции мы объявили указатель на массив. Такое преобразование имеет место и в случае объявления обычного статического массива const n=5; int a[n];. Так как a — константный указатель на начало массива, то a[i] равносильно *(a+i), где i=0,1,…,4.

Поэтому возникает вопрос, почему бы не помочь системе выполнить такое преобразование. Такая помощь реализуется следующим образом:

int MySum1 (int* ar, unsigned size)

{ int S=0; for (unsigned i=0; i< size; i++) S+=*(ar+i);

return S;

}

Это самый простой вариант использования указателя при работе с массивом. Здесь вместо ar[i] записали *(ar+i). Но последний вариант для компьютера “легче”. Дополнительную переменную-указатель здесь мы не использовали, а ограничились указателем на массив ar. Такой вариант приемлем как для статического, так и для динамического одномерных массивов.

Теперь должно быть понятно, почему индексы массивов в языках С и С++ начинаются с нуля. Это связано с тем, что индекс определяет не столько номер элемента, сколько его смещение относительно начала массива.

Так как ar+i=i+ar, то доступ к i -му элементу массива можно записать и так: *(i+ar) или даже более оригинально: i[ar].

Если по какой либо причине неизвестно количество элементов статического массива, то его можно определить следующим образом: sizeof(a)/sizeof(a[0]). Здесь учитывается, что все элементы массива имеют одинаковый размер. Важно также обратить внимание на следующее. Несколько раз напоминалось, что имя массива (a) — это константный указатель, в котором хранится адрес начала массива. Тогда возникает вопрос: sizeof(a) — это размер чего, ячейки для указателя или размер всего массива? Здесь сделано исключение. В этой операции массив “забывает” о связи с указателем, и её результатом является размер в байтах участка оперативной памяти, выделенного для всего массива, а не для указателя. Обратим внимание, что получается не количество элементов массива, а необходимый для всего массива объём памяти в байтах. Тогда для получения количества элементов в масссиве объём всей памяти разделили на объём памяти для одного элемента.

Но заметим, что если бы эту операцию использовали внутри функции MySum1 для ar, то sizeof(ar) — это объём памяти для указателя, а не для массива.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: