Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга C++.doc
Скачиваний:
24
Добавлен:
10.11.2019
Размер:
2.48 Mб
Скачать

За кулисами...

Давайте заглянем за кулисы... Начнем с того, что рассмотрим упрощенную схему организации памяти. Память типичного компьютера представляет собой массив последовательно пронумерованных и проадресованных ячеек, с которыми можно работать по отдельности или связаными кусками. Наверное Вы уже знаете, что память IBM PC совместимых компьютеров делится на 8-битовые байты. Когда мы описываем некоторую переменную или массив, в памяти выделяется непрерывная область для хранения этой переменной. Все строго учтено, поэтому каждый байт пронумерован (нумерация начинается с нуля). Номер байта, с которого начинается в памяти переменная, называется адресом этой переменной . Также об адресе говорят, что он указывает на определенный байт. Таким образом, указатель является просто адресом байта памяти. В языке С++ также предусмотрены операции, которые могут быть использованы для доступа к указателям и для манипулирования ними. Применительно к любому компьютеру верны следующие утверждения: один байт может хранить значение типа char, двухбайтовые ячейки могут рассматриваться как целое типа short, а четырехбайтовые - как целые типа long или int. Указатель это группа ячеек (как правило две или четыре), в которых может храниться адрес. Так, если с имеет тип char, а р – указатель, ссылающйся на с, то ситуация выглядит следующим образом:

Как работать с указателями?..

Первый шаг в применении указателя - присвоить ему значение адреса. Для этого надо иметь возможность получить адрес, по которому в памяти расположен какой-то другой объект. Унарный оператор & выдает адрес объекта, так что инструкция р=&с; присваивает адрес ячейки с переменной р  (говорят, что р указывает на с или, что то же, р ссылается на с). Оператор & применяется только к объектам, расположенным в пямяти. Его операндом не может быть ни выражение, ни константа.

        Унарный оператор * есть оператор раскрытия ссылки (или, унарная операция взятия косвенного адреса, или операция разыменования - запоминать ВСЕ необязательно, но знать что это такое - необходимо). Примененный к указателю он выдает объект, на который данный указатель ссылается. Предположим, что х и у целые, а ip- указатель на іnt. Следующие несколько строк показавают, каким образом объявляются указатели и используются операторы & и *.

int x=1, y=22, z[10];

int *ip; // ip – указатель на int

ip=&x; // тепер ip указывает на х

y=*ip; // y тепер равен 1

*ip=0 // x теперь равен 0

ip=&z[0]; //ip тепер указывает на z[0]

Описания x, y, и z Вам уже знакомы. Объявление указателя ip int *ip; буквально гласит следующее: выражение * ip есть указатель на целое.

Вы, наверное, заметили, что указателю разрешено ссылаться только на объекты заданого типа  (существует одно исключение: указатель на void может ссылаться на объекты любого типа, но к такому указателю нельзя применять оператор раскрытия ссылки. Об особенностях использования типа void мы поговорим позже)

Рассмотрим вопрос связанный с арифметическими операциями над указателями. Если ip ссылается на х целого типа, то * ip можно использовать в любом месте, где допустимо применение х, например:

*ip=*ip+10; //увеличивает ip на 10;

Унарные операторы * и & имеют более высокий приоритет, чем арифметческие операторы, так что встретив присваивание y=*ip+1 компилятор возмет то, на что указывает и добавит к нему 1, а результат присвоет переменной у. Аналогично *ip+=1 увеличивает на единицу то, на что ссылается ip; те же действия выполняют ++*ip и (*ip)++. В последней записи скобки необходимы, поскольку, если их не будет, увеличится значение самого указателя, а не то, на что он ссылается. Это обусловлено тем, что унарные операторы * и ++ имеют одинаковые приоритет и порядок выполнения - справа налево. И, наконец, так как указатели сами являются переменными, в тексте они могут встречаться и без оператора раскрытия ссылки. Например, если iq есть указатель на int, то iq=ip копирует содержимое ip в iq, чтобы ip и iq ссылались на один и тот же объект. Указатели можно использовать как операнды в арифметических операциях. Если у - указатель, то унарная операция у++; увеличивает его значение; теперь оно явлется адресом следующего элемента. Указатели и целые числа можно складывать. Конструкция y+n (y-указатель, n-целое число) задает адрес n-го объекта, на который указывает у. Это справедливо для указателей на любой тип; компилятор будет масштабировать приращение адреса в соответсвии с типом, определенным из соответсвующего объявления.

Любой адрес можно проверить на равенство (==) или неравнство (!=) со специальным значением NULL, которое позволяет определить ничего не адресующий указатель.

Заметим, что указатели можно сравнивать с помощью операций отношения (<, >, <=, >=, !=  и  ==). Однако следует быть осторожным, так как  в сравнении должны участвовать указатели, которые адресуются к данным одного и того же типа.