Оперативна меморија рачунара организована је као низ локација са придруженим адресама, где је најмања адресабилна јединица један бајт. Подаци у оперативној меморији записују се у узастопним бајтовима. На пример, податак типа int записује се у четири узастопна бајта, податак типа double у осам узастопних бајтова итд.
Показивачка променљива садржи меморијску адресу податка на кога показује (то је увек адреса бајта са најнижом адресом, односно, адреса првог бајта у низу узастопних бајтова). Иако су меморијске адресе цели бројеви, показивачки типови се у програмском језику C стриктно разликују од целобројног типа. Такође, у програмском језику C постоји више показивачких типова, где се показивачки тип одређује на основу типа податка на који показује.
Показивачка променљива декларише се на следећи начин…
tip *identifikator;
…где је tip тип податка на који се показује, а identifikator име показивачке променљиве. Приликом декларације није битно да ли постоји размак између звездице и типа или звездице и идентификатора – звездица се увек односи на идентификатор. У следећем примеру…
int* pa;
int *pb;
int * pc;
…декларисане су показивачкe променљивe pa, pb и pc које показују на податкe типа int.
Унарни оператор & (којег називамо адресним оператором, односно оператором референцирања) враћа меморијску адресу свог операнда, стим да операнд не може бити константа, нити израз. У следећем примеру…
int a = 3, *pa;
pa = &a;
…у меморијски простор целобројне променљиве a уписана је вредност 3, а у меморијски простор показивачке променљиве pa уписана је меморијска адреса променљиве a. За показивачку променљиву pa каже се да показује на целобројну променљиву a. Ово се може записати и у једној линији:
int a = 3, *pa = &a;
Поред улоге означавања показивачких променљивих, унарни оператор * (који се називама оператором дереференцирања) враћа вредност која се налази у меморијском простору на коју показивачка променљива показује, увек водећи рачуна о типу податка који се у њој налази. У следећем примеру…
int a = 3, *pa = &a;
printf("%d", *pa);
…у простор променљиве a уписана је вредност 3, у простор променљиве pa уписана је адреса променљиве a, па је на крају на стандардни излаз исписана вредност на коју показује pa. Шта ће се исписати на излазу? Исписаће се 3 јер је вредност на коју показује pa у ствари вредност променљиве a.
Резимирајмо све до сада. У следећем програму…
#include <stdio.h>
int main(void)
{
int x = 100, *px = &x;
printf("x : %d\n", x);
printf("&x : %p\n", &x);
printf("px : %p\n", px);
printf("*px : %d\n", *px);
return 0;
}
…на стандардном излазу исписаће се…
- вредност целобројне променљиве
x - адреса целобројне променљиве
x, тј.&x - вредност показивачке променљиве
px - и вредност показивачке променљиве на коју показује
px, тј.*px
…што може да изгледа овако:
x : 100
&x : 0000008E4F79F594
px : 0000008E4F79F594
*px : 100
Јасно је да су једнаке вредности променљиве x и променљиве на коју показује px, као и да је адреса променљиве x једнака са вредношћу променљиве px, док ће меморијске адресе бити различите приликом сваког покретања програма.
Ако се у изразу дереференцираном показивачу додељује вредност, онда измена његове вредности утиче и на простор на који показује (ако показује на променљиву, мења се садржај те променљиве). У следећем примеру…
#include <stdio.h>
int main(void)
{
int a, * pa;
a = 3;
pa = &a;
*pa = 6;
printf("%d", a);
return 0;
}
…у простор променљиве a уписана је вредност 3, у простор променљиве pa уписана је адреса променљиве a, па је у простор на који показује pa уписана вредност 6. Уписом вредности 6 у простор на који показује pa промењена је и вредност променљиве a на 6!