Опубликован: 02.02.2011 | Уровень: для всех | Доступ: свободно
Лекция 5:

Производные типы. Тип указатель: указатели на объекты

< Лекция 4 || Лекция 5: 123 || Лекция 6 >

Способы инициализации указателя

  1. Присваивание указателю адреса области памяти существующего объекта:
    • с помощью операции получения адреса:
      int a=5; 
      int *p=&a;
    • с помощью проинициализированного указателя
      int *r=p;

  2. Присваивание указателю адреса области памяти в явном виде:
    char *cp=(char*)0х В800 0000;
    где В800 0000 – шестнадцатеричная константа, ( char* ) – операция приведения типа.
  3. Присваивание указателю пустого значения:
    int *N=NULL; или int *N=0;

Спецификатор указателя при форматированном выводе

Если на экран необходимо вывести адрес, следует применять спецификатор %p.

%pспецификатор указателя.

Этот спецификатор формата заставляет функцию printf() выводить на экран адрес, формат которого совместим с типом адресации, принятой в компьютере.

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

С указателями можно выполнять следующие операции:

  • разыменование (*) – получение значения величины, адрес которой хранится в указателе;
  • взятие адреса (&);
  • присваивание;
  • арифметические операции
    • сложение указателя только с константой,
    • вычитание: допускается разность указателей и разность указателя и константы,
    • инкремент (++) увеличивает значение указателя на величину sizeof(тип);
    • декремент (--) уменьшает значение указателя на величину sizeof(тип);
  • сравнение;
  • приведение типов.

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

// Выбор данных из памяти с помощью разных указателей
// Использование функций приведения типов
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
  unsigned long L=12345678;
  char *cp=(char*)&L;
  int *ip=(int*)&L;
  long *lp=(long*)&L;

  cout <<"\n&L = "<<&L; 
  cout <<"\nL = "<<L;  
  cout <<"\n*cp = "<<*cp; 
  cout <<"\n*ip = "<<*ip;
  cout <<"\n*lp = "<<*lp;
  
  system("pause");
  return 0;
}

Пример 2.

//Операции над указателями
#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[]){
  int a,c,b;
  int  *ca, *cb;
  int *sa, *sb, *sc;
  cout << "a = "; cin >> a;
  cout << "b = "; cin >> b;  
  c=a+b;

  sb=&b;//инициализация указателей через взятие адреса
  sa=&a;
  sc =&c;
  //присваивание указателю значения выражения
  *sc = c+a-b;
  ca=sa;//присваивание указателю значения другого указателя
  cb=sb;
  *sa=12;//присваивание указателю значения константы

  cout << "\n*ca = " << *ca;
  cout << "\n*sa = " << *sa; 
  cout << "\n*cb = " << *cb; 
  cout << "\n*sb = " << *sb;
  cout << "\n*sc = " << *sc;

  cout << "\nca = " << ca; 
  cout << "\ncb = " << cb;
  cout << "\nsc = " << sc;

  cout << "\na = " << a;
  cout << "\nb = " << b;
  cout << "\nc = " << c;

  cout << "\n&a = " << &a; 
  cout << "\n&b = " << &b;
  cout << "\n&c = " << &c;

  cout << "\n*&a = " << *&a;  
  
  cout << "\n*cb-*ca = " << *cb-*ca;
  cout << "\n*cb+*ca = " << *cb+*ca;
  *cb+=2; //сложение с константой
  cout << "\ncb = " << cb;
  cb++; //инкремент
  cout << "\ncb = " << cb;
  ca--; //декремент
  cout << "\ncа = " << ca;
  cout << "\ncb-ca = " << cb-ca; 
  system("pause");
  return 0;
}

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

Пример 3.

#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
  int x=10;
  int y=10;
  int *xptr=&x;
  int *yptr=&y;
  
//сравниваем указатели
  if (xptr == yptr) 
    cout << "Указатели равны\n";
     else  
    cout << "Указатели неравны\n";

//сравниваем значения, на которое указывает указатель
  if (*xptr == *yptr) {
    cout << "Значения равны\n";
    } else { 
    cout << "Значения неравны\n";}
  system("pause");
  return 0;
}

В приведенном примере результат первой операции сравнения будет ложным, а второй – истинным, поскольку переменные x и y имеют одно и то же значение.

Ключевые термины

Адрес объекта – это адрес области оперативной памяти, по которому хранится объект в соответствии с особенностями представления типа.

Инициализация указателя – это определение значения указателя.

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

Непосредственно производные типы – это типы, которые являются производными от некоторых существующих типов, реализуя типы указателей, ссылки, функции преобразования типов.

Переименование типов – это задание нового имени для существующего типа.

Производные типы данных – это типы, полученные на основе более простых базовых типов.

Разыменование – это операция получения значения объекта, адрес которого хранится в указателе;

Составные производные типы – это типы, являющиеся производными от различных существующих или ранее объявленных типов.

Указатель – это именованный объект, предназначенный для хранения адреса области памяти.

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

Указатель-константа – это указатель, значение которого нельзя изменить в процессе выполнения программы.

Указатель-константа на константу – это указатель, для которого невозможно изменение как самого указателя, так и значения адресуемого объекта.

Краткие итоги

  1. В языке С++ производные типы данных классифицируют в зависимости от построения на производные и непосредственно производные.
  2. Для экономии памяти и времени, затрачиваемого на обращение к данным, в программах используют указатели на объекты.
  3. Указатель не является самостоятельным типом, он всегда связан с другим типом.
  4. Указатель может быть константой или переменной, а также указывать на константу или переменную.
  5. Указатель типа void указывает на область памяти любого размера. Разыменование такого указателя необходимо проводить с операцией приведения типов.
  6. До первого использования в программе объявленный указатель необходимо проинициализировать.
  7. С помощью указателей можно выполнять косвенную адресацию объектов.
  8. Над указателями определены операции: разыменование, взятие адреса, декремент, инкремент, увеличение (уменьшение) на целую константу, разность, определение размера.
  9. Над указателями определены операции сравнения.
< Лекция 4 || Лекция 5: 123 || Лекция 6 >
Денис Курбатов
Денис Курбатов
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!

Андрей Садовщиков
Андрей Садовщиков
Россия