Ukazatele v C++

C++ Pokročilé konstrukce v C++ Ukazatele v C++

Co jsou to ukazatele
Ukazatele, jak už název napovídá, na něco ukazují. Můžou ukazovat na různé proměnné, objekty nebo dokonce i na funkce. Ukazatel je sám o sobě 32bitová proměnná(na systémech Windows), jehož hodnota je adresa nějakého jiného objektu. No a adresou se rozumí nějaké číslo, které reprezentuje určitou pozici v operační paměti počítače. V reálném módu (v systému MS-DOS) je adresa reprezentována jako segment:offset, a lze ji zapsat jako 0x15FB:FF11. Obě části mají po 2Bytech. Naproti tomu v chráněném módu (charakteristický pro systémy Windows) je uložena v podobě selektor:offset. Selektor je 2Bytový index v tabulce adres, je to obdoba segmentu, pouze zde je to index do tabulky s adresami segmentů. Offset má 4Byty a je to posun vůči začátku segmentu. V tomto módu se používá pouze offset adresy.

Jednoduchý ukazatel lze vytvořit například takto:

int* pNumber = NULL; //Vytvori ukazatel
int number = 100;
pNumber = &number;//Priradi mu adresu promenne number
cout <<"Promenna number ma hodnotu " << number
     << " a jeji adresa je " << &number <<endl;

cout <<"Promenna pNumber ma hodnotu " << pNumber
     <<" a jeji adresa je " <<&pNumber
     <<"\nA hodnota v promenne na kterou ukazuje je "
     <<*pNumber;

Teď si to postupně vysvětlíme. Tak na prvním řádku vytváříme ukazatel. Děje se to tak, že za typ proměnné umístíme znak hvězdičky (*). To upozorní překladač že se nebude jednat o obyčejnou proměnnou, ale o ukazatel. Proč mu ale hned přiřazujeme nějakou hodnotu, a proč je to zrovna NULL? NULL je samo o sobě makro definující nulu(0). No a děje se tak proto, abychom zabranili možným pozdějším problémům (kterým se ale v tomto přehledném příkladu snad ani nelze dopustit) jako např. přiřazení hodnoty do neinicializovaného ukazatele. Pokud bychom totiž vynechali přiřazení oné nuly, byla by poté v tomto ukazateli opět nespecifikovatelná hodnota. Takže tento ukazatel by pak mohl ukazovat skoro kamkoli, třeba do paměti sloužící jinému programu. Kdybychom pak chtěli pomocí tohoto ukazatele zkusit změnit hodnotu v proměnné, na kterou měl ukazovat (avšak neukazuje), došlo by k tomu nejhoršímu - mohla by se přepsat pamět jiného běžícího procesu a pokud by na to Windows nebo jiný systém nepřišel a nezastavil to, tak by onen program(proces) mohl začít pracovat záhadně a hlavně nesprávně. Na dalším řádku vytváříme obyčejnou celočíselnou proměnnou, jejíž hodnotu hned nastavíme na 100. No a konečně přicházíme k tomu důležitému - inicializaci ukazatele správnou adresou. Jak je vidět, adresu jakéhokoli objektu lze zjistit tak, že před něj umístíme znak "&". Od teď ukazatel pNumber ukazuje na proměnnou number. Na dalších řádcích si jen ověřujeme, zda to tak opravdu je. Pokud program přeložite a spustíte, uvidíte že hodnota ukazatele je opravdu schodná s adresou proměnné number. Také je zde vidět že i sám ukazatel je někde uložen, tedy má svoji vlastní adresu, která je odlišná od adresy number.

Pokud budete chtit zjistit nebo změnit hodnotu proměnné, na kterou ukazatel ukazuje, použijete operaci zvanou dereferencování ukazatele. Zní to strašlivě, ale je to jednoduché. Pouze před název ukazatele umístíte hvězdičku a je to. Takže potom pNumber bude adresa, ale *pNumber bude hodnota na této adrese uložená.

Konstantní ukazatele

Používá se v případě, pokud nechcete nebo aby se změnila adresa umístěná v ukazateli, neboli jeho hodnota. Umožňuje však změnit hodnotu proměnné na kerou ukazuje. To ho odlišuje od ukazatele na konstantu popsaném níže. Konstantní ukazatel lze deklarovat takto:

int number = 1000;
int* const cpNumber = &number; //Vytvori konst. ukazatel
int hours = 24;

cpNumber = &hours;//CHYBA, snaha zmenit hodnotu konstanty
*cpNumber = 2000; //Toto je mozne

Pokud už se vám to začíná trochu plést, tak se ničeho neděste, zatim je to v pohodě. Uvidíte, za chvíli z toho asi budete mít hlavu jako pytel od banánů :)) Tohle bude jen procházka růžovým sadem. To pravé ořechové přijde až s ukazately na funkce ;)

Ukazatele na konstantu

Jak už sem zmínil výše, je to opak konstantního ukazatele. Zde se nesmí pomocí ukazatele měnit hodnota proměnné, na kterou ukazuje. Samotnou proměnnou však můžeme přímo změnit. A to, že se jedná o ukazatel na konstantu neznamená, že se nutně musí jednat jen o konstantu. Uvedeme si menší příklad:

int money = 100;
const int cMonth = 12;
const int* pPointer = &money; //Vytvori ukaz. na konstantu
money = 200; //Toto funguje
*pPointer = 300; //Toto uz ale ne
pPointer = &cMonth; //Priradime adresu konstanty
cMonth = 200; //CHYBA, nelze menit hodnotu konstatny
*pPointer = 300; //Take chyba, jak jinak

Co když ale máme obyčejný ukazatel, a přiřadíme mu adresu konstanty? Tak toto překladač samozřejmě nesmí dovolit, a také nedovolí, protože pak bychom hodnotu této konstanty mohli pomocí tohoto ukazatele měnit. Z výše uvedeného kódu ještě vyplývá, že opravdu ukazatel na konstantu nemusí nutně na konstantu ukazovat, jen se pomocí něho nesmí měnit její hodnota.


 

  Aktivity (4)

Článek pro vás napsal Jiří Pipošiar
Avatar
Moc toho tady o sobě prozrazovat nebudu, raději:)) Takže momentálně žiju v Klatovech(velkoměsto v západních Čechách), a 22.5.2003 jsem zde i odmaturoval na střední průmyslové škole. No a novinka - byl jsem přijat na Západočeskou univerzitu - Faku...

Jak se ti líbí článek?
Celkem (5 hlasů) :
3.83.83.83.8 3.8


 


Miniatura
Předchozí článek
Přetypování a operátory
Miniatura
Všechny články v sekci
Pokročilé konstrukce v C++

 

 

Komentáře

Avatar
NicharCZ
Neregistrovaný
Avatar
NicharCZ:

Zdravím, chtěl bych se zeptat na praktické využití pointers (ukazatelů). Je možné přiložit příklad?

Děkuji

 
Odpovědět 18.8.2013 20:05
Avatar
Kdosi
Neregistrovaný
Avatar
Odpovídá na NicharCZ
Kdosi:

Nemáš představivost? Místo předávání proměnných stačí předávat ukazatele... Obdoba toho je ref, out atp. Přesto mám ruční alokaci mnohem raději...

 
Odpovědět 13.10.2013 9:18
Avatar
Martin Rich
Člen
Avatar
Martin Rich:

const int* pPointer v posledním příkladě mění svou hodnotu (adresu) - na jinou promněnou - to mi odporuje definici "Zde se nesmí pomocí ukazatele měnit hodnota proměnné, na kterou ukazuje." - je to tak myšleno či se mýlím?

 
Odpovědět 9.9.2015 22:52
Avatar
Drahomír Hanák
Tým ITnetwork
Avatar
Odpovídá na Martin Rich
Drahomír Hanák:
const type* promenna

je pointer na konstantní typ

type* const promenna

je konstantní pointer na typ, který můžeš měnit

pPointer svoji hodnotu nemění, mění hodnotu, na kterou ukazuje (protože použil operátor dereference *)

Editováno 9.9.2015 23:01
 
Odpovědět  +1 9.9.2015 23:00
Avatar
Drahomír Hanák
Tým ITnetwork
Avatar
Odpovídá na Martin Rich
Drahomír Hanák:

Špatně jsem to přečetl, autor v komentářích popisuje, co je povolené a co ne. Pokud máš definici const int* pPointer, pak nemůžeš měnit hodnotu, na kterou ukazuje, ale samotný ukazatel měnit můžeš.

 
Odpovědět 9.9.2015 23:09
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.