Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Указатели и массивы




В Си существует самая тесная связь между указателями и массивами, поэтому лучше эти средства рассматривать вместе.

Как мы знаем, структура массива полностью соответствует структуре оперативной памяти – элементы массива занимают в ней подряд идущие ячейки. Значит, если описан массив

int mass[5];

то в оперативной памяти для его элементов выделяется пять подряд идущих ячеек:

К i -му элементу этого массива можно обратиться, назвав его индекс: mass[i].

Доступ к любому элементу массива, осуществляемый по его индексу (номеру), может быть выполнен при помощи указателя, причем это будет сделано быстрее. Опишем переменную ptr как указатель на данные целого типа:

int *ptr;

В результате присваивания

ptr = &mass[0];

эта переменная будет содержать адрес начального (нулевого) элемента этого массива, то есть указатель ptr будет указывать на элемент mass[0]:

Адрес начального элемента любого массива называется базовым адресом этого массива. Таким образом, сейчас указатель ptr содержит базовый адрес массива mass. Если увеличить значение указателя на единицу, то ptr + 1 будет указывать на следующий элемент массива, то есть на mass[1], ptr + 2 – на элемент mass[2] и так далее. В общем случае, если значение указателя увеличить на k, то можно получить адрес k -го элемента массива mass.

Значит, адрес любого элемента массива равен сумме его базового адреса, который является адресом его начального элемента, и смещения этого элемента от начала массива. Для начального (нулевого) элемента массива это смещение равно нулю, для первого элемента – единице, для второго – двум, для k -го оно равно k. Это верно для массива любого типа. Смысл выражения «увеличить указатель ptr на единицу», как и смысл любой арифметики с указателями, заключается в том, что ptr + 1 указывает на следующий за ptr элемент, а ptr + k – на k -й после ptr элемент массива.

Между индексированием элементов массива и арифметикой с указателями существует очень тесная связь, потому что имя любого массива в Си есть адрес его начального элемента, то есть имя массива является его базовым адресом. Значит,
в нашем примере присваивание

ptr = &mass[0];

можно записать в другом виде:

ptr = mass;

Это будет одно и то же: записи &mass[0] и mass эквивалентны.

Из всего этого следует, что в общем случае запись &mass[k] будет эквивалентна записи (mass + k), а сам k -й элемент массива можно определить как mass[k] или как *(mass + k). С другой стороны, если ptr – указатель, то в выражениях его можно использовать с индексом, то есть запись ptr[k] эквивалентна записи *(ptr + k).

Таким образом, элемент массива в Си разрешается изображать и в виде указателя со смещением, и в виде имени массива с индексом.

Между именем массива и указателем, выступающим в роли имени массива, однако существует различие. Указатель – это переменная, поэтому можно записать ptr = mass или ptr++. Но имя массива не является переменной, и записи типа mass = ptr или mass++ не допускаются.

Помимо рассмотренной операции сложения, над указателями можно выполнять следующие операции:

- складывать и вычитать указатели и целые данные,

- вычитать и сравнивать два указателя, ссылающиеся на элементы одного и того же массива,

- присваивать значение указателя другому указателю того же типа,

- присваивать указателю нуль и сравнивать его с нулем.

Над указателями нельзя выполнять следующие операции:

- складывать два указателя, перемножать их, делить, сдвигать, выделять разряды,

- складывать указатели со значениями типа float и double,

- присваивать указателю одного типа значение указателя другого типа (исключение составляют указатели типа void).

Указатели можно использовать и при работе с многомерными массивами:

int trio[5][2][3];

int *i_ptr;

Описан трехмерный массив trio целого типа и указатель ptr на данные целого типа. Присвоим этому указателю значение базового адреса массива:

i_ptr=&trio[0][0][0];

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

i_ptr=trio;

как это имеет место для векторов (одномерных массивов).

Доступ к j -му элементу i -й строки k -го слоя массива trio может быть осуществлен либо с помощью индексов:

trio[k][i][j]=1;

либо с помощью указателей:

*(i_ptr + k*(2*3) + i*3 + j)=1;

Как и в Паскале, в языке Си запрещается присваивать значения элементов одного массива другому массиву целиком:

float r[2][2], s[2][2];

r = s; // ошибка!

Эти ограничения можно обойти с помощью указателя:

float *f_ptr;

f_ptr = &s[0][0];

r = *f_ptr;

При этом элементам массива r будут присвоены значения соответствующих элементов массива s.






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных