Показивачи

Да се подсетимо – променљива је податак у програму који има:

  • своје име које представља адресу меморијске локације на којој се чува вредност тог податка
  • тип податка (int, float, double) који одређује скуп вредности које податак може имати, као и операције које се над тим податком могу вршити.

Овакав приступ подацима, где се на адреси у меморији чува ВРЕДНОСТ податка назива се директно адресирање.

Постоји и индиректно адресирање, код кога се у меморији чува адреса на којој је уписана вредност траженог податка. Индиректно адресирање се у програмском језику C (C++) реализује помоћу показивача.

Показивач (енгл. pointer) представља променљиву која чува адресу меморијске локације неке друге променљиве, константе или показивача.

Основне особине показивача су:

  • показивач може мењати вредност (тј. у различитим деловима програма може показивати на различите меморијске локације)
  • преко њега се може добити вредност променљиве чију адресу чува (на коју показује)
  • преко њега се може мењати вредност променљиве на коју показује

Када узимамо или мењамо вредност елемента на који показивач показује, кажемо да га дереференцирамо.

Показивачи могу да имају тип, али и не морају. Показивачи који имају тип, показују на одређени тип променљиве, нпр. целобројну. Показивачи који немају тип показују на било који тип података (код њих се као тип променљиве, односно тип показивача користи службена реч void).
Да би декларисали показивач, морамо ставити знак * испред његовог имена:

tip_na_koji_pokazuje * ime_pokazivača

Напомена: сасвим је небитно да ли се пише ‘tip* pok’, ‘tip *pok’ или ‘tip * pok’ jер компајлер ионако „не види“ ове размаке. На програмеру је да усвоји један од ових начина и да њега користи (то касније представља својеврсни „стил“ програмера“).
Када показивачу додељујемо почетну вредност, онда вршимо његову иницијализацију адресом неког другог објекта користећи знак амперсанд (&) или адресни оператор. Сада показивач садржи адресу тог објекта односно показује на њега. Синтакса иницијализације је

pokazivač = &neki_objekt;

пример:

#include <iostream>
using namespace std;
int main()
{
     int broj=5;
     cout << "Vrijednost varijable broj je "<<broj<<endl;
     cout << "Adresa varijable broj je "<<&broj<<endl;
     int* pokBroj=&broj;
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl;
}

Оно што је важно запамтити то је да је показивач адреса, тј. вредност показивача је адреса!

Ако желимо да добијемо вредност променљиве на коју показивач показује, испред имена показивача мора се навести ‘*’. Знак * се зове оператор дереференцирања или индирекције (енг. dereferencing, indirection operator).

#include <iostream>
using namespace std;
int main()
{
int broj=5;
cout << "Vrednost promenljive broj je "<<broj<<endl;
cout << "Adresa promenljive broj je "<<&broj<<endl;
int* pokBroj=&broj;
cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl; // koristi se samo ime pokazivaca, prikazuje se adresa
cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl; // koristi se "vrednost" pokazivaca, odnosno izvrseno je dereferenciranje pokazivaca pa se prikazije vrednost promenljive
}

резултат извршавања овог програма:

pokazivac-rezultat

Сада, када је показивач добио адресу на коју показује, над њим је могуће обављати радње попут инкрементирања (повећавање вредности за 1), декрементирања (смањивање вредности за 1), те рачунске операције. Али, ако не користимо знак дереференцирања => не мењамо вредност променљиве него адресу, па можемо добити чудне резултате!

#include <iostream>
using namespace std;
int main()
{
     int broj=5;
     cout << "Vrednost promenljive broj je "<<broj<<endl;
     cout << "Adresa promenljive broj je "<<&broj<<endl;
     int *pokBroj=&broj;
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl;
     cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl;
     cout << endl << endl;
     pokBroj++;// namera je bila da povecamo vrednost upisanu u memorijsku lokaciju pokBroj, tako da se vrednost promenljive broj poveca za 1
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl; // ovo je, u stvari, adresa na koju je smesten pokazivac
     cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl;// promenjena je vrednost pokazivaca, odnosno u adresu pokBroj je upisana nova adresa, a na toj adresi se nalazi nesto sto nismo ocekivali
     pokBroj+=2;
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl;// adresa pokazivaca ostaje nepromenjena
     cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl;//ponovo neocekivan rezultat, hteli smo izvrsiti operaciju broj=broj+2, pomocu pokazivaca pokBroj, ali smo mi umesto toga promenili vrednost koja je upisana na adresi pokBroj, a na toj adresi na koju pokBroj pokazuje ne nalazi se ono sto smo mi ocekivali
}

резултат:

pokazivac-rezultat1

Претходни програм требало је написати на следећи начин:

#include <iostream>
using namespace std;
int main()
{
     int broj=5;
     cout << "Vrednost promenljive broj je "<<broj<<endl;
     cout << "Adresa promenljive broj je "<<&broj<<endl;
     int *pokBroj=&broj;
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl;
     cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl;
     cout << endl << endl;
     (*pokBroj)++;
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl;
     cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl;
     (*pokBroj)+=2;
     cout << "Adresa pokazivaca pokBroj je "<<pokBroj<<endl;
     cout << "Vrednost pokazivaca pokBroj je "<<*pokBroj<<endl;
}

и резултат извршавања показује да смо добили баш оно што смо хтели:

pokazivac-rezultat2

Још једна важна напомена: показивачи су ограничени типом на који показују. Ако, на пример, одредите да показивач показује на целобројну вредност, не можете му придружити адресу реалне променљиве. Изузетак од овога правила чине показивачи типа void * који показују на неки неодређени тип податка тако да они могу показивати на било који тип података. Али, показивачи типа void * не могу бити иницијализовани, дакле не може им се доделити почетна вредност!

делови текста преузети са Škola C++: polja, pokazivači, reference (2)

Advertisements

2 thoughts on “Показивачи

Оставите одговор

Попуните детаље испод или притисните на иконицу да бисте се пријавили:

WordPress.com лого

Коментаришет користећи свој WordPress.com налог. Одјавите се / Промени )

Слика на Твитеру

Коментаришет користећи свој Twitter налог. Одјавите се / Промени )

Фејсбукова фотографија

Коментаришет користећи свој Facebook налог. Одјавите се / Промени )

Google+ photo

Коментаришет користећи свој Google+ налог. Одјавите се / Промени )

Повезивање са %s