Представете си паметта на компютъра като последователност от клетки памет, всяка по 1 byte. Тези клетки се номерират последователно във възходящ ред, така че всяка клетка има уникален номер с едно по-голям от този на предходната. Този номер всъщност представлява адресът на клетката – чрез него тя може да бъде локализирана бързо и лесно.

Когато декларираме променлива в C++, операционната система автоматично заделя място в паметта за нея. За да разберем точния адрес, на който е локализирана нашата променлива в паметта, можем за използваме специалния оператор „&“, който се поставя пред името на променливата. Пример:

  1. house = 6; // 6 стаи в къщата
  2. address = &house; // присвояваме адресът на house (4312)
  3. rooms = house; // присвояваме стойността на house (6)

За да направим нещата по-лесно разбираеми – представете си следната ситуация: Имаме променливата house (къща), която има за стойност целочислено число (броят на стаите в къщата). Адресът на променливата house в паметта можем да си представим като адреса на къщата (град, улица, номер..).

За допълнително улесняване на примерите ще приемем, че адресът на променливата house e 4312 – това разбира се е само примерен адрес, всъщност няма как да знаем адреса, преди действителното стартиране на програмата.

Стойностите на всяка от променливите, след изпълнението на кода, са показани на следната диаграма:

Уроци по програмиране

Променлива, която съхранява адреса на друга променлива (в случая address) наричаме указател. Указателите са много мощно свойство на езика C++ и имат много приложения в съвременното програмиране.

Използвайки указатели, можем директно да достъпим стойността на променливата към която той сочи. Това става просто като сложим знака * пред името на указателя. Продължавайки със стойностите от предишния пример, сега погледнете следния:

  1. sameHouse = *address;

Този код може да се преведе на разбираем език по следния начин – „sameHouse е равно на стойността, която се намира на адреса, посочен от address“. Тъй като указателят address сочи към променливата house, променливата sameHouse ще присвои нейната стойност, тоест 6. Или още по-просто казано, ако на даден адрес има къща със 6 стаи и ние отидем на този адрес, ще видим къща със 6 стаи (логично).

Уроци по програмиране

Забележете разликата между операторите & и *. Те имат противоположно значение. Можем да си ги превеждаме по следния начин:
& – адреса на
* – стойността, посочена от

Разгледайте внимателно следния код. Всички твърдения в него са верни:

  1. house == 6
  2. &house == 4312
  3. address == 4312
  4. *address == 6

Деклариране на указатели

Тъй като указателите имат способността директно да се отнасят към стойността на променливата към която сочат, е необходимо да бъдат декларирани и да им бъде указан съответният тип данни, към който ще сочат, защото не е едно и също да сочат към променлива от тип char и към променлива от тип int или float например. Декларирането на указатели става под следната форма:

тип * име

където тип е типа данни на променливата към която указателят е предназначен да сочи. Например:

  1. int * integer;
  2. double * realnumber;
  3. char * symbol;

Искам да подчертая, че звездичка (*), която използваме при декларирането на указателя, само означава, че той е указател и не бива да се бърка с оператора, който видяхме малко по-рано. Те са просто две различни неща, представени с еднакъв знак.

Сега погледнете следния код:

  1. #include <iostream>
  2. using namespace std;
  3. int main ()
  4. {
  5.      int * myptr;
  6.      int number1;
  7.      int number2;
  8.     myptr = &number1;
  9.     *myptr = 5; // присвояваме стойността 5 към мястото в паметта, посочено от указателя myptr (в случая променливата number1 се намира на това място)
  10.     myptr = &number2;
  11.     *myptr = 3; // преценете сами какво се случва тук?
  12.     number1 += number2;
  13.     cout << „number1 = „ << number1 << endl;
  14.     cout << „number2 = „ << number2 << endl;
  15.     return 0;
  16. }

Изходът от програмата е:

number1 = 8
number2 = 3

Какво всъщност се случва? Първо указателят myptr присвоява адреса на променливата number1. След това присвояваме стойността 5 към мястото в паметта, посочено от myptr, и тъй като в момента myptr сочи мястото в паметта на променливата number1, то на практика това променя стойността именно на променливата number1. За втората променлива е аналогично.

Това е основното за указателите. В следващия урок ще видим как можем да използваме указателите, като параметър на функция, за да можем да обработваме масиви в нашите функции.

Автор: Мартин Михайлов