Основні операції над покажчиками

 

Мова Сі надає можливість використання адрес змінних програми за допомогою основних операцій - & та *:

За допомогою основних операцій можна отримати значення адреси змінної, а використовуючи непряму адресацію - одержати значення змінної за її адресою.

Призначення цих операцій:

&ім'я_змінної - одержання адреси; визначає адресу розміщення значення змінної визначеного типу;

*ім'я-покажчика - отримання значення визначеного типу за вказаною адресою; визначає вміст змінної, розміщеної за адресою, що міститься у даному покажчику; це - непряма адресація (інші назви - "зняття значення за покажчиком" або "розіменування" ).

Операція &

Оператор присвоювання значення адреси покажчику має вигляд:

Ім'я_змінної_покажчика = & ім'я змінної;

Наприклад:

int i, *pi; /* pi - змінна покажчик */

pi = &i; /* pi одержує значення адреси 'i' */

Операція & - визначення адреси змінної - повертає адресу ОП свого операнда. Операндом операції & повинне бути ім'я змінної того ж типу, для якого визначений покажчик лівої частини оператора присвоювання, що одержує значення цієї адреси.

У вищенаведеному прикладі це тип int.

Операції * і & можна писати впритул до імені операнду або через пробіл. Наприклад: &і, * pi.

Непряма адресація змінної за допомогою операції * здійснює доступ до змінної за покажчиком, тобто повернення значення змінної, розташованої за адресою, що міститься у покажчику. Операнд операції * обов'язково повинен бути типу покажчик. Результат операції * - це значення, на яке вказує (адресує, посилається) операнд. Тип результату - це тип, визначений при оголошенні покажчика.
У загальному вигляді оператор присвоювання, що використовує ім'я покажчика та операцію непрямої адресації, можна представити у вигляді:

ім'я змінної = * ім'я-покажчика;

де ім'я-покажчика - це змінна або константа, що містить адресу розміщення значення, необхідного для змінної лівої частини оператора присвоювання.

Наприклад:

i= *pi; /* 'i' одержує значення, розташоване за адресою,

що міститься в покажчику 'pi' */

Як і будь-які змінні, змінна pi типу покажчик має адресу і значення. Операція & над змінною типу покажчик: &pi - дає адресу місця розташування самого покажчика, pi - ім'я покажчика визначає його значення, a *pi - значення змінної, що адресує покажчик.

Звичайно, усі ці значення можна надрукувати. Наприклад, за допомогою наступної програми:

#include <stdio.h>

void main()

{
char c = 'A';

int i = 7776;

int *pi = &i;

char *pc = &c;

printf ("pi=%u,*pi=%d, &pi=%u\n", pi, *pi, &pi);

printf ("pc=%u, *pc=%c, &pc=%u\n", pc, *pc, &pc);

}

У результаті виконання буде виведено:

 

 

Одне з основних співвідношень при роботі з покажчиками - це симетричність операцій адресації та непрямої адресації. Вона полягає в тому, що:

&х == х,

тобто вміст за адресою змінної х є значення х. Наприклад, оголошення покажчика pi і змінних i та j:

int *pi, i = 123, j;

pi = &i; /*-присвоювання покажчику значення адреси i */

j = *pi; /* - присвоювання j вмісту за адресою pi */

Тут змінна j отримує вміст, розташований за адресою змінної i, тобто значення змінної, що адресує покажчик pi:

j = * pi = * &i = i;.

Два останніх вищенаведених оператора виконують те саме, що один оператор:

j = i.

Далі наведений приклад програми виводу значень покажчика і вмісту, розташованого за адресою, що він зберігає.

#include<stdio.h>
void main()
{
int i = 123, *pi = &i;

printf("розмір покажчика pi = %d\n", sizeof(pi));
printf("адреса розміщення покажчика pi=%u\n", &pi) ;
printf("адреса змінної i = %u\n", &i) ;
printf("значення покажчика pi = %u\n", pi) ;
printf("значення за адресою pi = %d\n", *pi) ;
printf("значення змінної i = %d\n", i) ;
}

Результати виконання програми:

 

 

Наступна програма демонструє найпростіше практичне використання покажчиків, виводячи звичайну послідовність літер алфавіту:

#include <stdio.h>

char c; /* змінна символьного типу*/

main()

{

char *pc; /* покажчик на змінну символьного типу*/

pc=&c;

for(c='A';c<='Z';c++)

printf("%c",*pc);

return 0;

}

У операторі printf("%c",*pc) має місце розіменування покажчика (*рс) - передача у функцію значення, що зберігається за адресою, яка міститься у змінній рс. Щоб дійсно довести, що рс є псевдонімом с, спробуємо замінити *рс на с у виклику функції - і після заміни програма працюватиме абсолютно аналогічно. Оскільки покажчики обмежені заданим типом даних, типовою серйозною помилкою їх використання буває присвоєння адреси одного типу даних покажчика іншого типу, на що компілятор реагує таким чином:
"Suspicious pointer conversion in function main()"