Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование / WORD / Лекции по ЯП (часть 3).doc
Скачиваний:
138
Добавлен:
15.04.2015
Размер:
1.34 Mб
Скачать

Указатели в языке Си

Указатель — это переменная, содержащая адрес другой переменной.

Объявление указателя выглядит следующим образом:

имя_типа *имя_указ;

имя_типа — любой из типов данных С. Он определяет тип переменной, на которую указывает указатель.

Звездочка (*) — это знак операции ссылки по указателю, и в данном случае он означает, что имя_указ является указателем на переменную типа имя_типа.

Указатели можно объявлять вместе с обычными переменными.

Инициализация указателей

Инициализируется указатель оператором присваивания:

указатель=&переменная,

& - операция взятия адреса.

Когда знак операции (*) стоит перед именем указателя, такая конструкция обозначает переменную, на которую указывает указатель, а операция называется разыменованием. .

Использование значения перемен путем указания ее имени называется прямым обращением к переменной. Ис­пользование значения переменной через указатель на нее называется косвенным обращении или ссылкой по указателю (адресу).

Потенциальные опасности

Указатели могут нести потенциальные опасности. Это связано с использованием неинициализированного указателя в левой части оператора присваивания.

Например, в этом операторе объявляется указатель на значение типа int

int *ptr;

Этот указатель еще не инициализирован, поэтому ни на что не указывает. Точнее он не указывает ни на что известное. У неинициализированного указателя есть какое-то значение, просто мы его не знаем. Во многих случаях это 0. Допустим, этот неинициализированный указатель используется в операторе присваивания: *ptr = 12;

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

Поэтому необходимо корректно инициализировать указатели перед тем, как их использовать. Это необходимо делать самостоятельно, ни в коем случае не полагаться на компилятор.

Если переменная многобайтная, то адрес переменной фактически представляет собой адрес первого (младшего) байта из занимаемых ею.

Хотя указатели могут быть полезны и при работе с простыми переменными, наиболее удобны они в работе с массивами. В языке С указатели и массивы тесно связаны.

Имя массива без квадратных скобок является указателем на первый элемент массива. Например, если объявлен массив data[], то data — это адрес первого элемента данного массива. Получить адрес первого элемента массива можно и таким способом: &data[0];

В языке С справедливо соотношение (data == &data[0]).

Имя массива является постоянным указателем (адресной константой): его нельзя изменить, и оно остается фиксированным все время выполнения программы. Поэтому при работе можно объявить отдельный указатель и инициализировать его, чтобы он указывал на массив.

Пример.

short arr1[6], *p_arr1;

float arr2[3], *p_arr2;

p_arr1= arr1; p_arr2= arr2;

В массиве short – arr1 следующий элемент массива находится на два байта дальше в памяти, чем предыдущий и адрес следующего элемента соответственно на 2 больше, чем адрес предыдущего. В массиве float – arr2 адрес каждого следующего элемента на 4 больше, чем предыдущего.

Как же обращаться к последовательным элементам массива с помощью указателя? Из приведенных примеров видно, что указатель нужно увеличивать на 2 для перебора элементов типа short, и на 4 — в массиве типа float. Обобщая, можно сказать, что указатель увеличивается на sizeof(тип_данных) для обращения к следующему элементу.