Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Прикладное программирование.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
439.97 Кб
Скачать

1.11. Ссылки и указатели

1.11.1. Ссылки

Ссылка (referenсe) - это переменная особого вида, которая представляет собой альтернативное имя (псевдоним, alias) другой переменной:

int &a = b;

В данном примере a - новое альтернативное имя для переменной b. a и b ссылаются на одно и то же место в памяти.

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

/////////////////////////////////////////////////////////////////////////////

// Прикладное программирование

// Пример 14. Ссылки

//

// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru

// СПб НИУ ИТМО

/////////////////////////////////////////////////////////////////////////////

// подключение библиотеки ввода-вывода

#include <iostream>

// подключение стандартного пространства имен для использования библиотек

using namespace std;

/////////////////////////////////////////////////////////////////////////////

// функция main начинает исполнение программы

void main()

{

//----------------------

int i=1; // объявление переменной

int &r=i; // объявление и инициализация ссылки на переменную

// вывод на экран значений переменной и ссылки на нее

cout<<i<<endl; // 1

cout<<r<<endl; // 1

cout<<endl;

// вывод на экран адресов переменной и ссылки на нее

cout<<&i<<endl; // 0x0012ff6c

cout<<&r<<endl; // 0x0012ff6c

cout<<endl;

//----------------------

i+=5; // изменение переменной

// вывод на экран значений переменной и ссылки на нее

cout<<i<<endl; // 6

cout<<r<<endl; // 6

cout<<endl;

//----------------------

i-=5; // изменение переменной

// вывод на экран значений переменной и ссылки на нее

cout<<i<<endl; // 1

cout<<r<<endl; // 1

cout<<endl;

//----------------------

r=0; // изменение ссылки

// вывод на экран значений переменной и ссылки на нее

cout<<i<<endl; // 0

cout<<r<<endl; // 0

cout<<endl;

}

/////////////////////////////////////////////////////////////////////////////

1.11.2. Указатели

На хранение адреса в современных вычислительных системах отводится 32 бита (4 байта) или 64 бита (8 байт). Это значит, что теоретически программы могут управлять памятью объемом около 4096 Мб (а для 64-разрядных систем - около 16777215 Тб). Для работы с памятью каждая из её ячеек нумеруется.

Пусть для хранения переменной i типа int отводится 4 байта. Тогда структура хранения этой переменной в оперативной памяти может иметь следующий вид:

адрес ячейки

байт памяти

......

.........

0x00A0

00000000

0x00A1

00000000

0x00A2

00000000

0x00A3

00000001

0x00A4

.........

.......

..........

Указатель (pointer- это переменная особого вида, предназначенная для хранения адреса объекта (адреса ячейки памяти, в которых хранится значение переменной). Обычно переменная непосредственно содержит некоторое значение. Указатель же содержит адрес переменной, которая, в свою очередь, содержит значение. Диапазон значений для любого указателя включает специальный адрес 0 (null) и диапазон положительных целых чисел, который интерпретируется как машинные адреса.

Для получения значения переменной хранящейся в ячейке, на которую указывает указатель, используется оператор разыменования (*).

Объявление указателя

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

int *p;

что означает, что переменная p имеет тип int * (т.е. указатель на int) и указывает на объект типа int.

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

double *xPtr, *yPtr;

В данном случае переменные xPtr, и yPtr являются указателями на значения типа double. Когда звездочка появляется в объявлении, она не является операцией разименования, она только сообщает, что переменная объявляется как указатель.

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

Для получения адреса ячейки памяти, в которой хранится переменная, и последующей инициализации переменной типа указатель используется операция получения адреса (&).

int i=1; // объявление целой переменной i

int *p; // объявление переменной типа указатель, т.е. значение по адресу p является целым числом

p=&i; // p=0x00A0 (оператор получения адреса)

В данном примере, значение переменной p представляет собой адрес ячейки (указатель на то место в памяти), в которой хранится значение переменной i.

Операция разименования

Для получения значения переменной хранящейся в ячейке, на которую указывает указатель, используется оператор разыменования (*). Если нужно использовать значение переменной, хранящейся по адресу p, перед p нужно ставить оператор разыменования:

int i=1; // объявление целой переменной i

int *p ; // объявление переменной типа указатель, т.е. значение по адресу p является целым числом

p=&i; // p=0x00A0 (оператор получения адреса)

int t=*p+1; // эквивалентно t=i+1;

p++; // прибавляем 1 к указателю – переходим к следующей ячейке памяти с другой переменной

Рассмотрим пример работы с указателем.

/////////////////////////////////////////////////////////////////////////////

// Прикладное программирование

// Пример 15. Указатели

//

// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru

// СПб НИУ ИТМО

/////////////////////////////////////////////////////////////////////////////

// подключение библиотеки ввода-вывода

#include <iostream>

// подключение стандартного пространства имен для использования библиотек

using namespace std;

/////////////////////////////////////////////////////////////////////////////

// функция main начинает исполнение программы

void main()

{

//----------------------

int i=1; // объявление переменной

int* p; // объявление указателя на переменную

p=&i; // инициализация указателя на переменную

// вывод на экран значения переменной

cout<<i<<endl; // 1

// вывод на экран ссылки

cout<<p<<endl; // 0x0012ff6c

// вывод на экран значения переменной, на которую указывает указатель

cout<<*p<<endl; // 1

cout<<endl;

//----------------------

i+=5; // изменение переменной

cout<<i<<endl; // 6

cout<<*p<<endl; // 6

cout<<endl;

//----------------------

*p-=5; // изменение переменной, хранящейся по указателю

cout<<i<<endl; // 1

cout<<*p<<endl; // 1

cout<<endl;

//----------------------

p++; // изменение указателя (смещение в памяти на следующюу переменную)

cout<<i<<endl; // 1 (значение переменной не изменилось)

cout<<p<<endl; // 0x0012ff70 (адрес ячейки памяти изменился)

cout<<*p<<endl; // ???? (что хранится по новому адресу - неизвестно)

cout<<endl;

//----------------------

p=0; // изменение указателя (указатель никуда не указывает)

cout<<p<<endl; // 0x00000000

cout<<*p<<endl; // ошибка !!! по этому адресу нет никаких значений

cout<<endl;

}