Добавил:
Лабы/курсовые по программированию (С++/Verilog HDL), Теория и Практика Помехоустойчивого Кодирования Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1сем Дагаев / lectures_3.pdf
Скачиваний:
28
Добавлен:
09.03.2022
Размер:
769.01 Кб
Скачать

/*

// указателя

.............................*/

38.6.Операции с указателями

Вязыке Си указатели наделены большими возможностями. Об этом свидетельствует размер перечня тех операций, которые можно выполнять с указателями:

Разыменование,

Взятие адреса,

Присваивание,

Индексирование указателей

Арифметические действия с указателями,

Сравнение указателей.

Дополнительные сведения о разыменовании указателей

Как отмечалось выше, разыменование – операция позволяющая получить доступ к объекту, на который установлен указатель. Однако эта операция допустима не ко всем указателям. Остановимся на тех категориях указателей,

ккоторым нельзя применять разыменование:

Недействительный указатель.

Нетипизированный указатель.

Нулевой указатель

Приведем примеры недопустимых разыменований.

/* Примеры недопустимых разыменований указателей */

int* p = NULL;

/* Недопустимо разыменовывать нулевой указатель*/

*p = 10;

int n = 5;

 

void*

p3 = &n;

/* Недопустимо разыменовывать нетипизированный

*p3 = 10;

 

 

указатель p3*/

char* p4;

/* Недопустимо разыменовывать

*p4 = ’A’;

/*

 

неинициализированный указатель p4 */

. . . . . . . . . . . . . . . . . . . . . . . . . . . */

Заметим, что к категории операторов разыменования относятся еще два оператора:

Оператор [], который используется при работе с массивами.

Оператор ->, который используется при работе со структурами.

Присваивание указателей

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

96

некорректной работе программы. Остановимся на этом вопросе подробнее. Рассмотрим ряд частных случаев. Начнем с присваивания типизированных указателей. Корректность такой операции не вызывает сомнений только в том случае, когда совпадают базовые типы обоих указателей. В противном случае такую операцию следует считать недопустимой. Приведем пример программного кода, в котором будут встречаться оба вида присваиваний.

/*

Корректные и некорректные присваивания типизированных

int n = 10;

указателей

*/

 

 

double x = 20.3;

 

int *p1, p2;

 

 

double* p3;

 

 

p1

= &n;

/* допустимое присваивание

*/

p2

= p1;

/* допустимое присваивание

*/

p3

= p2;

/* недопустимое присваивание, т. к. не

совпадают базовые типы указателей

*/

/* конец программного кода примера

*/

 

Отметим, что, несмотря на

семантическую недопустимость

присваивания p3 = p1 в приведенном выше примере компилятор языка Си ограничивается выводом предупреждения (Компилятор языка С++ в этой ситуации выводит сообщение об ошибке). Работа языка Си с указателями свидетельствует о его пониженной типизации. Это обстоятельство следует рассматривать как крайне опасным последствиям. Одна из рекомендаций по преодолению этих неприятностей заключается в предварительной компиляции программного кода компилятором языка С++.

Одному указателю можно присвоить значение другого указателя. Однако некоторые присваивания, которые допускает язык Си, могут привести к некорректной работе программы. Остановимся на этом вопросе подробнее. Рассмотрим ряд частных случаев. Начнем с присваивания типизированных указателей. Корректность такой операции не вызывает сомнений только в том случае, когда совпадают базовые типы обоих указателей. В противном случае такую операцию следует считать недопустимой. Приведем пример программного кода, в котором будут встречаться оба вида присваиваний.

/*

Корректные и некорректные присваивания типизированных

int n = 10;

указателей

*/

 

 

double x = 20.3;

 

int *p1, p2;

 

 

double* p3;

 

 

p1

= &n;

/* допустимое присваивание

*/

p2

= p1;

/* допустимое присваивание

*/

p3

= p2;

/* недопустимое присваивание, т. к. не совпадают

 

 

базовые типы указателей

*/

/* конец программного кода примера

*/

97

Отметим, что, несмотря на недопустимость присваивания p3 = p1 в приведенном выше примере компилятор языка Си ограничивается выводом предупреждения (Компилятор языка С++ в этой ситуации выводит сообщение об ошибке).

Операция взятия адреса для указателя. Указатели на указатели

Пусть имеется следующий фрагмент программы

//..

int n = 5; int *p = &n; int **pp = &p;

Переменная pp является указателем на указатель или двухуровневым указателем. Эта переменная получена применением оператора взятия адреса & к указателю p. Указатели на указателиприменяются на практике. Например, в качестве параметров функций (см. прототип функции strtok).

Указатели и операция индексирования

Рассмотрим следующий фрагмент программного кода:

#define MSIZE 5 #include <stdio.h> int main(void)

{

int x[MSIZE] = {1, 3, 5, 7, 9}; int *p = &x[1];

printf(“p[1] = %d”, p[1]); // ..

}

В рассматриваемом фрагменте программы объявлен указатель p, который инициализирован адресом второго элемента массива x. Затем функции printf() к указателю p применен оператор индексные скобки []. В результате выполнения этого фрагмента программы на экране получим p[1] = 5.

Арифметические операции с указателями

Арифметические операции применяются к укзателям, которые работают с массивами. К числу допустимых арифметических операций к таким указателям относятся:

++ (инкремент),

--(декремент),

сложение с целым числом,

вычитание целого числа.

вычисление разности двух указателей. Рассмотрим слеющий программный код:

#define MSIZE 5 #include <stdio.h>

98

Соседние файлы в папке 1сем Дагаев