Процедурное программирование на языке С. Часть 1. Основные понятия языка С: Методические указания к лабораторным работам по курсам «Алгоритмические языки и программирование» и «Процедурное программирование», страница 9

intb[] = {24,15};

charc = ‘G’;

char s[] = {‘h’, ‘t’};

a                       f                        b[0]                   b[1]                   c           s[0]      s[1]

10

?

24

15

G

h

t

32000 32001   32002   32003   32004   32005   32006  32007   32008  32009  320010

Значение переменной a занимает 2 байта, начиная с адреса 32000. Остальные байты распределены следующим образом:

·  2 байта, начиная с адреса 32002,  –  для переменной f , значение  не определено;

·  2 байта, начиная с адреса 32004, –  для значения b[0], b[0] = 24;

·  2 байта, начиная с адреса 32006, –  для значения b[1], b[1] = 15;

·  значение переменной с занимает 1 байт,   адрес этого байта 32008;

·  значение каждого элемента символьного массива с именем s занимает по 1 байту,   адрес s[0] –   32009, адрес s[0] –   32010.

Каждое из чисел 32000, …, 32010, как и любой другой адрес, можно сохранить в некоторой переменной. Для этого такую переменную следует объявить. Возникает вопрос: какой тип должен быть у переменной, предназначенной для хранения машинного адреса другой переменной? Ответом на этот вопрос и является понятие указатель.

Таким образом, в общем случае указатель – это переменная (или константа), предназначенная для хранения машинного адреса некоторого объекта: переменной,  функции, структуры, объединения….

Рассмотрим частный случай указателя: переменную-указатель. В соответствии с синтаксисом языка С оператор объявления переменной-указателя имеет следующую форму:

<спецификация типа > * <имя переменной>;

В операторе объявления переменной-указателя

<спецификация типа > * <имя переменной>;          объявляется переменная с

                                                                  именем, которая является

                                                                    указателем на переменную

                                                                       типа

В качестве <спецификации типа> можно использовать любой базовый или производный тип данных, <имя переменной> – это идентификатор, соответствующий переменной, предназначенной для хранения  адреса.

Например, для работы с  адресами переменных  a ии с адресами элементов массива с именем b, можно объявить  переменную-указатель:   int * p;  Далее эту переменную можно использовать: p=&a; …   p=&f;  …  p=&b[0]; …  p=&b[1];   …  p=b;

Следует заметить, что для работы с адресом переменной с  и адресами элементов массива с именем s (т.е. объектов типа char),   переменная-указатель должна быть объявлена по-другому:      char * q;

3.2. ОПЕРАЦИИ С УКАЗАТЕЛЯМИ. АДРЕСНАЯ АРИФМЕТИКА

В языке С с переменными-указателями допустимы следующие операции:

1.  присваивание указателю некоторого значения – адреса объекта;

2.  получение адреса переменной-указателя;

3.  получение значения того объекта (частный случай – переменной), на который указатель ссылается;

4.  операции изменения значения самого указателя;

5.  операции сравнения значений указателей.

В то время как унарная операция ‘&’ может применяться к  переменной любого типа, показывая, что интерес представляет адрес этой переменной, а не ее текущее значение,  –  унарная операция ‘*’ (которую не следует  путать с бинарной операцией умножения) может применяться только к переменной типа указатель,  обеспечивая доступ к содержимому участка памяти, адресуемого указателем.  Если в программе есть оператор p=&aто  выражение *pможно описать словами разными способами:

·  *p –  это  то, что содержится по адресу, на который указывает p (в нашем примере число 10);

·  *p –  разыменование указателяp;

·  *p –  раскрытие ссылки (или разадресация);

·  *p –  запись/взятие значения по адресу, который хранится в переменной p.