|
Программирование >> Аргументация конструирования
Второе знакомство с указателями вэ/ной гмгёе... Операции с указателями Объявление и иснользование массивов указателей зык C++ позволяет работать с указателями так, как если бы они были пере-tXit менными простых типов. (Концепция указателей изложена в главе 8, Первое знакомство с указателями в C++ .) Однако операции над указателями требуют знания некоторых тонкостей; именно они и рассматриваются в этой главе. Опе1гации с tffcasaeieJJUiU Некоторые из операций, описанных в главе 3, Выполнение математических операций , могут быть применены к указателям. В этом разделе рассматривается применение арифметических операций при работе с указателями и массивами (с массивами вы познакомились в главе 7, Хранение последовательностей в массивах ). В табл. 9.1 приведены базовые операции над указателями. Таблице 1. Три операции над указателями ОПЕРАЦИЯ РЕЗУЛЬТАТ ДЕЙСТВИЕ
В этой таблице имеет тип int (здесь не приведены операции, близкие к сло- жению и вычитанию, такие как ++ и +=, которые также могут применяться к указателям). Модель памяти, построенная на примере домов (так эффективно использованная в предыдущей главе), поможет понять, как работают приведенные в таблице операции с указателями. Представьте себе квартал, в котором все дома пронумерованы по порядку. Дом, следующий за домом 123 Main Street, будет иметь адрес 124 Main Street (или 122 Main Street, если вы идете в противоположную сторону, поскольку вы левша или живете в Англии). Очевидно, что в таком случае через четыре дома от моего будет находиться дом с адресом 127 Main Street. Адрес этого дома можно записать как 123 Main Street + 4 = 127 Main Street И наоборот, если поинтересоваться, сколько домов находится между домом 123 и 127, ответом будет четыре: 127 Main Street - 123 Main Street = 4 Понятно, что любой дом отстоит сам от себя на расстояние ноль домов: 123 Main Street - 123 Main Street = О Повторное знакомство с массивами в свете указателей Обратимся к странному и мистическому миру массивов. Еще раз воспользуемся в качестве примера домами моих соседей. Массив тоже очень похож на городской квартал. Каждый элемент массива выступает в качестве дома в этом квартале. Дома - элементы массива - отсчитываются по порядку от начала квартала. Дом на углу отстоит на 0 домов от угла, следующий дом отстоит на 1 дом от угла и Теперь представим себе массив из 32-х однобайтовых значений, имеющий имя charArray. Если первый элемент массива находится по адресу 0x110, тогда массив будет продолжаться вплоть до адреса Таким образом, элемент массива cha- гАггауЮ: находится но адресу 0x110, charArray[1] - но адресу 0x111, charArray [2) - по адресу 0x112 и т.д. Можно создать указатель ptr на нулевой элемент массива. После выполнения строки ptr = &charArray[0]; указатель ptr будет содержать адрес 0x110. Можно прибавить к этому адресу целочисленное смещение и перейти к необходимому элементу массива. Операции над массивами с использованием указателей приведены в табл. 9.2. Эта таблица демонстрирует, каким образом добавление смещения п вызывает переход к следующему элементу массива charArray. Таблица 9.2.Добавление смещения
Как видите, добавление смещения к указателю на массив равнозначно переходу к соответствующему значению. Таким образом, если char* ptr = 4charArray[0] ;, то * (ptr + и) соответствует элементу charArray [n] . Поскольку имеет более высокий приоритет, чем сложение, операция *ptr + п привела бы к сложению п со значением, на которое указывает ptr. Чтобы выполнить сначала сложение и лишь затем переход к переменной по указателю, следует использовать скобки. Выражение * (ptr + п) возвращает элемент, который находится по адресу ptr плюс п элементов. В действительности соответствие между двумя формами выражений настолько строго, что C++ рассматривает элемент массива как * + n), где ptr указывает на первый элемент array. C++ интерпретирует array [п] как * [0] +п). Таким образом, если дано char charArray [20], то charArray оп- ределяется как bcharArray [ О ]. Имя массива, записанное без индекса элемента, интерпретируется как адрес нулевого элемента массива (или просто адрес массива). Таким образом, можно упростить приведенную выше запись, поскольку [n] C++ интерпретирует как *(array + n) . Использование операций над указателями для адресации внутри массива Концепция соответствия между индексацией массива и арифметикой указателей весьма полезна (если бы это было не так, здесь бы не было данного подраздела). Например, функция displayArray(), которая выводит содержимое целочислеп-ного массива, может быть реализована следующим образом: displayArray - отображает элементы массива, имеющего длину nSize void displayArray(int IntArray [ ] , int nSize) { cout << Значения элементов массива равны:\п ; for (int n = 0; n < nSize; n+ + ) cout n : IntArray [n] Vn ; cout << \n ; Эта версия функции использует операции над массивами, которые знакомы нам по предыдущим главам. Если воспользоваться для написания этой функции указателями, программа приобретет такой вид: displayArray - отображает элементы массива, имеющего длину nSize void displayArray(int IntArray[], int nSize) { cout << Значения элементов массива равны:\n , int* pArray = intArray; for (int n = 0; n < nSize; n + +, pArray + +) { cout n : *pArray \n ; cout \ n ; Этот вариант функции displayArray начинается с создания указателя на первый элемент массива intArray. Буква p в начале имени неременной означает, что эта переменная являет f Um 1 ся указателем 15. После этого функция считывает все элементы массива по порядку. При каждом выполнении оператора for происходит вывод текущего элемента из массива IntArray. Этот элемент находится по адресу рАггау, который увеличивается на единицу при каждом выполнении цикла. Можно сказать, что функция почти не изменилась и выполняет такие же операции, как и предыдущая версия, однако использование указателей - более распространенная практика, чем работа с массивами. По ряду причин программисты избегают работать с массивами. Чаще всего указатели используются для работы с символьными массивами. Однако это не более чем соглашение, и ви не обязаны начинать имена всех указателей с буквы р. - Прим. ред.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |