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


 

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

29038. Условия применения свайных фундаментов. Классификация свай по материалу, форме продольного и поперечного сечения 42.5 KB
  Сваи погружаемые в грунт в готовом виде в зависимости от материала из которого они изготовляются подразделяются на железобетонные деревянные стальные и комбинированные. Железобетонные сваи получившие наибольшее распространение в практике строительства подразделяются: по форме поперечного сечения на квадратные квадратные с круглой полостью полые круглого сечения прямоугольные тавровые и двутавровые рис.1; по форме продольного сечения на призматические цилиндрические с наклонными боковыми гранями пирамидальные...
29039. Понятие о висячих сваях и сваях-стойках. Определение несущей способности свай-стоек 28.5 KB
  По характеру передачи нагрузки на грунт сваи подразделяются на висячие сваи и сваистойки. К сваямстойкам относятся сваи прорезающие толщу слабых грунтов и опирающиеся на практически несжимаемые скальные или малосжимаемые грунты крупнообломочные грунты с песчаным заполнителем глины твёрдой консистенции. Сваястойка практически всю нагрузку на грунт передаёт через нижний конец так как при малых вертикальных перемещениях сваи не возникают условия для проявления сил трения на её боковой поверхности рис. Сваястойка работает как сжатый...
29040. Определение несущей способности висячих свай по таблицам СНиП. Понятие о негативном трении и его учёт при определении несущей способности свай 35.5 KB
  Расчёт несущей способности вертикально нагруженных висячих свай производится как правило только по прочности грунта так как по прочности материала сваи она всегда заведомо выше.0385 широко применяемый в практике проектирования и известный под названием практического метода позволяет определять несущую способность сваи по данным геологических изысканий. Метод базируется на обобщении результатов испытаний большого числа обычных и специальных свай вертикальной статической нагрузкой проведенных в различных грунтовых условиях с целью...
29041. Динамический метод определения несущей способности одиночной сваи. Понятие об отказе. Уравнение работ. Контроль за сопротивлением свай при их забивке 28.5 KB
  Динамический метод определения несущей способности одиночной сваи. При молотах ударного действия скорость погружения сваи принято характеризовать величиной её погружения от одного удара называемой отказом сваи. По величине отказа который замеряется при достижении сваей проектной отметки можно судить о её сопротивлении поскольку чем меньше отказ тем очевидно больше несущая способность сваи. Динамический метод и заключается в определении несущей способности сваи по величине её отказа на отметке близкой к проектной.
29042. Определение числа свай в фундаменте. Конструирование ленточных свайных фундаментов 27 KB
  Определение числа свай в фундаменте. Конструирование ленточных свайных фундаментов. Зная несущую способность сваи Fα и принимая что ростверк обеспечивает равномерную передачу нагрузки на все сваи фундамента необходимое число свай n на 1 м длины ленточного фундамента определяется по формуле: 1 где γк коэффициент надёжности принимаемый в зависимости от способа определения несущей способности сваи; N01 расчётная нагрузка на 1 м длины ленточного фундамента. Число свай на 1 м найденное по формуле 1 может быть дробным.
29043. Определение числа свай в фундаменте. Конструирование отдельно стоящих свайных фундаментов 22 KB
  Определение числа свай в фундаменте. Конструирование отдельно стоящих свайных фундаментов. Зная несущую способность сваи Fα принимая что ростверк обеспечивает равномерную передачу нагрузки на все сваи фундамента необходимое число свай n в кусте определяют по формуле 1 где γк коэффициент надёжности принимаемый от способа определения несущей способности сваи; N01 расчётная нагрузка на куст. Полученное по формуле 1 число свай округляется в сторону увеличения до целого числа.
29044. Договор аренды: понятие, элементы, права и обязанности сторон 125.5 KB
  Договор аренды имущественного найма это соглашениепо которому арендодатель обязуется предоставить арендатору имущество за плату во временное владение и пользование или во временное пользование. Поэтому правовое регулирование аренды обусловлено также платным характером временного пользования. Общие положения об аренде представляют собой нормы которые могут применяться к любым видам договора аренды если иное не установлено правилами об этих договорах ст.
29045. Договор подряда: понятие, элементы, права и обязанности сторон 51.5 KB
  По договору подряда одна сторона подрядчик обязуется выполнить по заданию другой стороны заказчика определенную работу и сдать ее результат заказчику а заказчик обязуется принять результат работы и оплатить его. Особенности данного договора: предметом договора является изготовление или переработка вещи либо выполнение другой работы. Оплачивается результат работы который подлежит передаче заказчику а не процесс; сторонами договора являются: подрядчик физическое или юридическое лицо. Отдельные виды договора подряда: бытовой подряд;...
29046. Договор хранения: понятие, элементы, права и обязанности сторон 87 KB
  Договор хранения: предмет договора виды форма договоров хранения. Права и обязанности сторон по договору хранения Договор хранения соглашение по которому хранитель должен хранить вещь переданную ему поклажедателем и возвратить ее в сохранности. Договоры хранения можно разделить на два вида: бытовые как правило безвозмездные и коммерческие.