Файл: Pobegaylo_A._C_Cplus_dlya_studenta.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.12.2020

Просмотров: 4243

Скачиваний: 28

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Часть I. Язык программирования С 

66 

  int s = 0; 
  if (!s) 
    goto err; 
  ++s; 
err:--s;     /* s = -1 */ 

В настоящее время в программировании инструкция 

goto

 приме-

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

 


background image

  

 
 

Г Л А В А  

 
 
 

Указатели и массивы 

 

5.1. Указатели 

Указатель

 —  это  переменная  или  именованная  константа,  кото-

рая содержит адрес (в памяти) другой переменной, именованной 

константы  или  функции.  В  этом  разделе  будут  рассмотрены 

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

объявления  указателя  нужно  перед  именем  переменной,  которая 
объявляется  как  указатель,  поставить  символ 

*

.  В  этом  случае 

переменная  является  указателем  на  данные,  тип  которых  задан 

спецификатором типа. Например: 

  int  *ip;     /* указатель на целое число */ 
  char *cp;     /* указатель на символ */ 
  double *dp;   /* указатель на плавающее число */ 

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

*

 ставят не перед пере-

менной, а после типа, на который ссылается указатель. Например: 

  int* ip; 

Но  в  этом  случае  следует  избегать  ошибки,  которая  возможна, 

если несколько указателей объявляются в одну строку. Например: 

  int* p1, p2; /* p1 - указатель, p2 – переменная типа int */ 

Чтобы  в  одной  инструкции  объявить  несколько  указателей  на 
один тип, нужно перед каждым указателем ставить символ 

*

. На-

пример: 

  int *p1, *p2;  /* p1, p2 - указатели */ 

  

 


background image

Часть I. Язык программирования С 

68 

При  объявлении  указателя  желательно  сразу  же  его  проинициа-
лизировать, что значительно облегчает отладку программы. Если 
при объявлении указателя его начальное значение неизвестно, то 
указателю  нужно  присвоить  значение  символической  константы 

NULL

, которая равна нулю. Например: 

  int  *p = NULL; 

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

NULL

, то при отладке програм-

мы  сразу  видно,  что  этому  указателю  забыли  присвоить  нужное 
значение.  Если  же  указатель  не  инициализировать  при  объявле-
нии,  то  в  нем  будет  находиться  "неопределенное  значение".  
В этом случае обращение к памяти через такой указатель являет-
ся ошибкой, которую довольно сложно обнаружить. 
Часто  для  числовых  типов  данных  и  указателей  используют  об-
щее название — 

скалярные типы данных

5.2. Преобразование  
типов указателей 

В языке программирования C можно преобразовывать типы ука-
зателей.  Явное  и  неявное  преобразование  типов  указателей  под-
чиняется следующим правилам: 

 

указатель на любой тип данных может быть приведен к указа-
телю  на  любой  другой  тип  данных.  Если  приведение  типов 
указателей  неявное —  то  компилятор  может  выдать  преду-
преждение; 

 

указатель типа 

void*

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

тип  данных  и  наоборот,  причем  эти  операции  взаимно  обра-
тимы; 

 

указатель  может  быть  преобразован  в  интегральный  тип  дан-
ных и наоборот, при этом указатель рассматривается как чис-
ло  без  знака;  если  преобразование  выполняется  неявно,  то 
компилятор может выдать предупреждение; 


background image

Глава 5. Указатели и массивы 

69 

 

выравнивание  адресов  на  границы,  кратные  длине  типа  дан-
ных, не учитывается, поэтому операция преобразования типов 
указателей может дать неопределенный результат; 

 

указатель, значение которого равно 

NULL

, преобразовывается в 

целое число, значение которого равно 0, и наоборот. 

В  языке  программирования  С++  приведение  типов  указателей 
подчиняется следующим правилам: 

 

указатель на любой тип данных может быть приведен к указа-
телю на любой другой тип данных только явно; 

 

указатель типа 

void*

 можно только явно привести к указателю 

на любой тип данных; указатель на любой тип данных неявно 
приводится к указателю типа 

void*

 

указатель может быть преобразован в интегральный тип и на-
оборот только явно. 

Остальные два правила остаются без изменения. 

5.3. Операторы определения адреса  
и обращения по адресу 

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

&

, который называется 

оператором опре-

деления адреса

 и имеет следующий вид: 

  &операнд 

Здесь 

операндом

  должно  быть  L-value,  которое  удовлетворяет 

двум ограничениям: 

 

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

 

не имеет спецификатор класса памяти 

register

Например: 

  int n; 
  int *p = &n;  /* p указывает на переменную n */ 

Получить значение переменной или именованной константы, ад-
рес которой хранится в указателе, можно при помощи 

оператора 


background image

Часть I. Язык программирования С 

70 

обращения по адресу

  или,  другими  словами, 

оператора разыме-

нования

, который имеет следующий вид: 

  *операнд 

Здесь 

операндом

  должен  быть  указатель.  Возвращает  оператор 

обращения по адресу L-value. Например: 

  int n = 2, m; 
  int *p = &n; 
  m = *p;    /* m = 2 */ 
  *p = 3;    /* n = 3 */ 

Особенно отметим, что работа оператора обращения по адресу не 
определена,  если  указатель  содержит  ошибочный  адрес.  В  этом 
случае  может  произойти  как  прерывание  программы,  так  и  ус-
пешное  завершение  операции  разыменования,  но  полученные 
данные будут ошибочными. Ошибку, возникшую во втором слу-
чае, особенно трудно обнаружить. 
Два последовательных оператора получение адреса и обращение 
по адресу аннулируют друг друга независимо от порядка их сле-
дования. 
Приоритет операторов определения адреса и обращения по адре-
су совпадает с приоритетом унарных арифметических и побито-
вых операторов. Эти операторы ассоциативны справа налево. 

5.4. Указатели на константы  
и константные указатели 

При  работе  с  указателями  следует  различать  использование  мо-
дификатора доступа 

const

  перед  типом  переменной,  на  которую 

ссылается указатель, и перед самим указателем. В первом случае 
указатель  ссылается  на  типизированную  константу,  а  во  вто-
ром — является константным указателем. Например: 

  const int n = 2; 
  const int *p = NULL;  /* p – указатель на константу */ 
  p = &n;  /* правильно, т. к. p – указатель на константу */ 


Смотрите также файлы