Основні операції над покажчиками
Мова С++ надає можливість використання адрес змінних програми за допомогою основних операцій - & та *:
За допомогою основних операцій можна отримати значення адреси змінної а використовуючи непряму адресацію - одержати значення змінної за її адресою.
Призначення цих операцій:
- & ім'я змінної - одержання адреси; визначає адресу розміщення значення змінної визначеного типу;
- * ім'я-покажчика - отримання значення визначеного типу за вказаною адресою; визначає вміст змінної, розміщеної за адресою, що міститься у даному покажчику; це - непряма адресація (інші назви - "зняття значення за покажчиком" або "розіменування" ).
Оператор присвоювання значення адреси покажчику має вигляд:
iм'я_змінної_покажчика = & ім'я змінної.
Наприклад,
int i, *pi; // pi -змінна покажчик
pi = &i; // pi одержує значення адреси 'i'.
Операція "&" - визначення адреси змінної повертає адресу свого операнда. Операндом операції "&" повинне бути ім'я змінної того ж типу, для якого визначений покажчик лівої частини оператора присвоювання, що одержує значення цієї адреси. У вищенаведеному прикладі це тип int.
Операції "*" і "&" можна писати впритул до імені операнду або через пробіл. Наприклад: &і, * pi.
Непряма адресація змінної за допомогою операції "*" здійснює доступ до змінної за покажчиком, тобто повернення значення змінної, розташованої за адресою, що міститься у покажчику. Операнд операції "*" обов'язково повинен бути типу покажчик. Результат операції "*" - це значення, на яке вказує (адресує, посилається) операнд. Тип результату - це тип, визначений при оголошенні покажчика.
У загальному вигляді оператор присвоювання, що використовує ім'я покажчика та операцію непрямої адресації, можна представити у вигляді:
ім'я змінної =* ім'я-покажчика;
де ім'я-покажчика - це змінна або константа, що містить адресу розміщення значення, необхідного для змінної лівої частини оператора присвоювання.
Наприклад,
i= *pi; // 'i' одержує значення, розташоване за адресою, що міститься в покажчику 'pi'
Як і будь-які змінні, змінна pi типу покажчик має адресу і значення. Операція & над змінною типу покажчик: &pi - дає адресу місця розташування самого покажчика, pi - ім'я покажчика визначає його значення, a *pi - значення змінної, що адресує покажчик.
Приклад 1. Приклади застосування покажчиків.
#include <iosteam.h>
void main()
{
char c = 'A';
int i = 7776;
int *pi = &i;
char *pc = &c;
cout<< "\npi="<<pi<<", *pi="<<*pi<<", &pi="<< π
cout<<"\npc="<<pc<<", *pc="<<*pc<<", &pc="<< &pc;
}
У результаті виконання буде виведено:
pi = 65522, *pi = 7776, &pi = 65520
pc = 65525, *рс = А, &pc = 65518
Приклад 2. Приклади застосування покажчиків.
#include < iostream.h >
int main ( )
{
int x = 10;
int *px = &x;cout << " x =" << x << endl;
cout << "*px =" << *px << endl;
x* = 2; // або x = x*2;
cout << " Нове значення* px =" << *px << endl;
*px += 2; // або *px =*px + 2;
cout << " Нове значення* px=, тобто х=" << x << endl;
return 0;
}
Результат виконання програми:
x = 10
*px = 10
Нове значення *px = 20
Нове значення*px, тобто x = 22
Одне з основних співвідношень при роботі з покажчиками - це симетричність операцій адресації та непрямої адресації. Вона полягає в тому, що:
*&х == х,
тобто зміст за адресою змінної х є значення х. Наприклад, оголошення покажчика pi і змінних i та j:
int *pi, i = 123, j;
pi = &i; //-присвоювання покажчику значення адреси i
j = *pi; // - присвоювання j вмісту за адресою pi
Тут змінна j отримує pміст, розташований за адресою змінної i, тобто значення змінної, що адресує покажчик pi: j = * pi = * &i = i;. Два останніх вищенаведених оператора виконують те саме, що один оператор: j = i.
Для повного остаточного розуміння процесів, що відбувається у пам'яті при маніпуляції з покажчиками, розглянемо ще такий фрагмент:
void func()
{
int х;
int *pх; // pх - покажчик на змінну типу int
pх= &х ; // адреса змінної х заноситься в рх
*pх=77; // число зберігається за адресою, на яку вказує рх
}
Розглянемо цей приклад на конкретному малюнку: функція займає область пам'яті, починаючи з адреси 0х100, х знаходиться за адресою 0х102, а рх - 0х106. Тоді перша операція присвоювання, коли значення &х(0х102) зберігається в рх, матиме вигляд,
зображений на малюнку 1.
:
Рисунок 1 - Розподіл пам'яті
Наступну операцію, коли число 77 записується за адресою, яка знаходиться в рх та дорівнює 0х102 (адреса х), відображає наступний малюнок. Запис *рх надає доступ до вмісту комірки, на яку вказує рх.
Рисунок 2 - Розподіл пам'яті, якщо задано значення
Приклад 3. Програма виводу значень покажчика і змісту, розташованого за адресою, що він зберігає.
#include<iostream.h>
void main()
{
int i = 123, *pi = &i; // pi-покажчик на значення типу int
cout<<"\n розмір покажчика pi = "<< sizeof(pi);
cout<<"\n адреса розміщення покажчика pi="<< &pi ;
cout<<"\n адреса змінної i = "<< &i ;
cout<<"\n значення покажчика pi = "<< pi ;
cout<<"\n значення за адресою pi = "<< *pi ;
cout<<"\n значення змінної i = "<<i ;
}
Результати виконання програми:
розмір покажчика pi = 4
адреса розміщення покажчика pi = 1245060
адреса змінної i=1245060
значення покажчика pi = 1245060
значення за адресою pi = 123
значення змінної i = 123