Представете си паметта на компютъра като последователност от клетки памет, всяка по 1 byte. Тези клетки се номерират последователно във възходящ ред, така че всяка клетка има уникален номер с едно по-голям от този на предходната. Този номер всъщност представлява адресът на клетката – чрез него тя може да бъде локализирана бързо и лесно.
Когато декларираме променлива в C++, операционната система автоматично заделя място в паметта за нея. За да разберем точния адрес, на който е локализирана нашата променлива в паметта, можем за използваме специалния оператор „&“, който се поставя пред името на променливата. Пример:
- house = 6; // 6 стаи в къщата
- address = &house; // присвояваме адресът на house (4312)
- rooms = house; // присвояваме стойността на house (6)
За да направим нещата по-лесно разбираеми – представете си следната ситуация: Имаме променливата house (къща), която има за стойност целочислено число (броят на стаите в къщата). Адресът на променливата house в паметта можем да си представим като адреса на къщата (град, улица, номер..).
За допълнително улесняване на примерите ще приемем, че адресът на променливата house e 4312 – това разбира се е само примерен адрес, всъщност няма как да знаем адреса, преди действителното стартиране на програмата.
Стойностите на всяка от променливите, след изпълнението на кода, са показани на следната диаграма:
Променлива, която съхранява адреса на друга променлива (в случая address) наричаме указател. Указателите са много мощно свойство на езика C++ и имат много приложения в съвременното програмиране.
Използвайки указатели, можем директно да достъпим стойността на променливата към която той сочи. Това става просто като сложим знака * пред името на указателя. Продължавайки със стойностите от предишния пример, сега погледнете следния:
- sameHouse = *address;
Този код може да се преведе на разбираем език по следния начин – „sameHouse е равно на стойността, която се намира на адреса, посочен от address“. Тъй като указателят address сочи към променливата house, променливата sameHouse ще присвои нейната стойност, тоест 6. Или още по-просто казано, ако на даден адрес има къща със 6 стаи и ние отидем на този адрес, ще видим къща със 6 стаи (логично).
Забележете разликата между операторите & и *. Те имат противоположно значение. Можем да си ги превеждаме по следния начин:
& – адреса на
* – стойността, посочена от
Разгледайте внимателно следния код. Всички твърдения в него са верни:
- house == 6
- &house == 4312
- address == 4312
- *address == 6
Деклариране на указатели
Тъй като указателите имат способността директно да се отнасят към стойността на променливата към която сочат, е необходимо да бъдат декларирани и да им бъде указан съответният тип данни, към който ще сочат, защото не е едно и също да сочат към променлива от тип char и към променлива от тип int или float например. Декларирането на указатели става под следната форма:
тип * име
където тип е типа данни на променливата към която указателят е предназначен да сочи. Например:
- int * integer;
- double * realnumber;
- char * symbol;
Искам да подчертая, че звездичка (*), която използваме при декларирането на указателя, само означава, че той е указател и не бива да се бърка с оператора, който видяхме малко по-рано. Те са просто две различни неща, представени с еднакъв знак.
Сега погледнете следния код:
- #include <iostream>
- using namespace std;
- int main ()
- {
- int * myptr;
- int number1;
- int number2;
- myptr = &number1;
- *myptr = 5; // присвояваме стойността 5 към мястото в паметта, посочено от указателя myptr (в случая променливата number1 се намира на това място)
- myptr = &number2;
- *myptr = 3; // преценете сами какво се случва тук?
- number1 += number2;
- cout << „number1 = „ << number1 << endl;
- cout << „number2 = „ << number2 << endl;
- return 0;
- }
Изходът от програмата е:
number1 = 8
number2 = 3
Какво всъщност се случва? Първо указателят myptr присвоява адреса на променливата number1. След това присвояваме стойността 5 към мястото в паметта, посочено от myptr, и тъй като в момента myptr сочи мястото в паметта на променливата number1, то на практика това променя стойността именно на променливата number1. За втората променлива е аналогично.
Това е основното за указателите. В следващия урок ще видим как можем да използваме указателите, като параметър на функция, за да можем да обработваме масиви в нашите функции.
Автор: Мартин Михайлов