4868

Указатели. Адресная арифметика. Ссылки

Лекция

Информатика, кибернетика и программирование

Указатели. Адресная арифметика. Ссылки. Указатели – особый тип данных. Указатель хранит адрес, по которому в памяти располагается некоторый объект (переменная, массив, функция). Можно упрощенно представить память компьютера в виде массива после...

Русский

2012-11-28

41 KB

8 чел.

Указатели. Адресная арифметика. Ссылки.

Указатели – особый тип данных. Указатель хранит адрес, по которому в памяти располагается некоторый объект (переменная, массив, функция). Можно упрощенно представить память компьютера в виде массива последовательно пронумерованных (адресованных) ячеек (байт). Любой переменной соответствует определенный участок памяти, представляющий собой непрерывную «цепочку» байт необходимого размера. Размер зависит от типа переменной. Например, переменная типа char всегда занимает ровно 1 байт, а переменная типа int может занимать 2 и больше байта (в зависимости от архитектуры компьютера и используемого компилятора). Соответственно, зная адрес начала участка памяти, выделенного для некоторой переменной, а также её тип, можно обеспечить чтение и запись этой переменной косвенным образом, через её адрес. Возможность такой косвенной работы с переменными (а также с массивами и функциями) осуществляется с помощью указателей.

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

 тип_переменной * имя_указателя;

Адрес переменной можно получить с помощью оператора &, в следующем примере указатель p инициализируется адресом переменной i:

int i = 10; 

int * p = & i;

Указателю любого типа можно присвоить значение 0, что означает, что указатель не адресует никакой переменной.

Косвенное обращение к переменной, адрес которой хранит указатель, осуществляется с помощью оператора разыменовывания (dereferencing) *, в приведенном ниже примере значение переменной d изменяется косвенным образом через указатель pd:

double d = 10;

 double * pd = & d;

*pd = 20;

std::cout << "d: " << d << std::endl;

Попытка косвенного обращения через указатель, имеющий нулевое значение, приведет к ошибке времени выполнения (run-time).

Указатели одного типа можно присваивать друг другу, при этом оба указателя будут ссылаться на один и тот же объект:

 

 float f = 1.0;

 float * pf1 = & f; // pf1 хранит адрес переменной f

 float * pf2 = pf1; // pf2 тоже хранит адрес переменной f

* pf2 = 2.0;       // теперь f == 2.0

 float g = * pf1;   // теперь g == f (2.0)

Указатель не может адресовать объект другого типа. Такие операции запрещены, потому что интерпретация компилятором объектов, адресуемых указателем, зависит от типа указателя:

 

 int i = 10;

   float * pf = & i; // ошибка

Иногда возникают ситуации, когда нужно только само значение адреса, а не объект, на который он указывает (например, нужно сравнить адрес с каким-то другим). Для этого существует специальный указатель void, который может адресовать любой тип данных. Однако, поскольку тип объекта, адресуемого таким указателем, неизвестен, никакие манипуляции с объектом через этот указатель не допустимы. Все, что можно сделать – присвоить его значение другому указателю или сравнить его с какой-либо адресной величиной.

  int i = 10;

  float f = 5.0;

  void * pv = & i; // допустимо

  pv = & f; // допустимо

  *p v = 1; // ошибка!

Применение оператора взятия адреса & к объекту типа int возвращает результат типа int*. Если ту же операцию применить к объекту типа int * (указатель на int), получим указатель на указатель на int, т.е. int**. int** – это адрес переменной, которая содержит адрес переменной типа int. В следующем примере, разыменовав ppi, мы получим переменную типа int*, содержащую адрес переменной i. Чтобы получить значение переменной i, операцию разыменовывания к ppi надо применить дважды:

 

      int i = 10;

  int * pi1 = & i; // pi1 получает адрес i

  int ** ppi = & pi1; // ppi получает адрес pi1

  int * pi2 = * ppi;  // pi2 получает значение pi1 косвенно,

                      // через указатель ppi. Фактически,

                      // теперь pi2 тоже содержит адрес i

  

  int j = **ppi; // j получает значение i косвенно,

                 // используя двойную адресацию

Адресная арифметика.

 Указатели могут быть использованы в арифметических выражениях. К указателю можно прибавлять или вычитать целое значение. Прибавление к указателю 1 увеличивает хранящееся в нем значение адреса на размер области памяти, используемый переменной соответствующего типа. Это позволяет использовать указатели при работе с массивами: поскольку в массивах все элементы располагаются в памяти последовательно, прибавление к указателю 1 означает «перевод» его на следующий элемент массива:

      int A[10];

  int * it = & A[0]; // Указатель на начало массива

  int * end = & A[10]; // Указатель на конец массива,

                       // фактически, это адрес участка памяти,

                       // расположенного сразу после последнего

                       // элемента массива

  while ( it != end ) // пока не дошли до конца массива

  {

     *it = rand(); // записываем в текущий элемент случайное число

     ++it; // увеличиваем указатель на 1,

           // т.е. переходим к следующему элементу массива

  }

 Ссылки.

Ссылочный тип служит для задания переменной дополнительного имени (синонима). Ссылка позволяет косвенно манипулировать переменной, аналогично указателю. Чаще всего ссылки используются в качестве формальных параметров функций. Ссылочный тип описывается указанием оператора взятия адреса & перед именем переменной. Ссылка обязательно должна быть инициализирована. Определив ссылку, невозможно изменить её так, чтобы работать с другим объектом.

  int i = 10 , j = 5;

  int & ri = i; // ri - синоним переменной i

  int & ri2; // Ошибка - ссылка не инициализирована

Все операции со ссылкой относятся к адресуемой ей переменной, в том числе присваивание и взятие адреса:

  ri = j; // i получает значение j через ссылку ri

  ri++; // i увеличивается на 1 через ссылку ri

     int * pi = & ri; // указатель pi получает значение

                   // адреса i через ссылку ri


 

А также другие работы, которые могут Вас заинтересовать

42800. Анализ информационных потребностей пользователей предметной области «Народное образование области» 684.5 KB
  Вместе с тем информационные потребности пользователей меняются со временем, что должно быть учтено в методике проектирования КИМПО: она должна быть ориентирована не столько на первоначальное создание модели, сколько на интеграцию новой информационной потребности с текущей моделью.
42801. Разработка специализированного цифрового функционального узла 6.35 MB
  Генератор чисел на базе счетчика Джонсона. Варианты построения счетчика Джонсона и выбор оптимального в соответствии с критерием оптимизации. Сигнал (R) имеет отрицательную полярность и длительность более Т и менее 1.5Т. В результате воздействия сигнала (R) генератор чисел должен установиться в исходное состояние и сформировать на своих выходах первое число из заданной последовательности.
42802. Расчетная АСР 258.49 KB
  При автоматизации технологических объектов управления ТОУ широко применяют одноконтурные системы регулирования АСР обеспечивающие стабилизацию выходных координат объектов. Проектирование таких АСР предполагает знание статических и динамических характеристик ТОУ позволяющих произвести расчет системы регулирования – определить структуру регулятора и найти параметры его настройки. Тогда по аналогии с критерием Найквиста можно сформулировать следующее условие: если разомкнутая АСР имеет степень колебательности...
42803. Электроиндуцированные упругие деформации в кристаллах ниобата лития 329.46 KB
  Точечная группа симметрии: 3m. Приложено электрическое поле В см под углом 600 к главной оси симметрии. Область науки в задачу которой входит описание и объяснение структуры кристаллов на основе законов симметрии и пространственных соотношений расстояний между атомами называется кристаллографией. Поскольку в данном кристалле имеется ось симметрии третьего порядка то использование метода прямой проверки в декартовых координатах невозможно.
42804. Разработка программного обеспечения, ведение базы данных “Прокат видеокассет” 2.21 MB
  Видеотека Имя поля Тип данных Названиеописание Длина поля Код кассеты Numeric Указывается код видеокассеты. 5 Жанр Numeric Указывается жанр фильма. 10 Наименование Chrcter Указывается название кассеты. 18 Режиссер Chrcter Указывается режиссер данной видеокассеты.
42805. Сравнительная характеристика автоматической двухшпиндельной вакуум-закаточной машины 2.16 MB
  1 СВЕДЕНИЯ ОБ ОБЬЕКТЕ ОБРАБОТКИ Для производства жестяных банок необходима жесть уплотняющие материалы. При производстве цельно штамповочных банок требуется жесть уплотняющие материалы и материал для смазки жести перед штамповкой банок. Кроме того для производства консервных банок используют белую лакированную жесть электролитического лужения она более экономична так как толщина оловянного покрытия составляет 061мКр. Жесть черная рулонная лакированная применяют для...
42806. Использование переходных металлов и их соединений в технологии сенсорных микро-наносистем 313.59 KB
  Настоятельная необходимость отслеживать все аспекты состояния окружающей среды в реальном времени постоянно растет, и это вызвано возрастающими связями загрязнения окружающей среды с нашим здоровьем и безопасностью. Необходимо также иметь возможность определять содержание основных компонентов и примесей в различных средах.
42807. Анализ конструкции мобильного телефона Samsung i8910 HD с использованием методик FMEA и FTA 7.54 MB
  Попытки научного подхода к оценке качества предпринимались давно. Так, еще в 1930 г. немецкий доктор-инженер К. Комментц установил для кораблей, предназначенных для мелководья, что всякое уменьшение осадки судов на 1 % приводит к повышению цены на 0,6%. Несколько более сложным у него оказалось влияние вместимости судна и других параметров качества.
42808. Технология швейного производства на примере РУП «БХПО» 2.6 MB
  Совершенствование швейного производства предусматривает внедрение высокопроизводительного оборудования поточных линий расширение ассортимента и улучшение качества одежды выпуск изделий пользующихся повышенным спросом. Технология современного швейного производства все более становится механической ее эффективность в первую очередь зависит от применяемого оборудования. Выбор швейного оборудования зависит от особенностей обрабатываемых изделий и материалов. Механизация и автоматизация производства приводит к расширению перечня используемого...