Home >> C++ návod >> Ukazatele - 2.část

Ukazatele - 2.část

V předchozí části této lekce jsme si vysvětlili princip funkce ukazatelů a ukázali jsme si pár základních příkladů, jak je možné ukazatele použít. Na tyto znalosti navážeme v této části, kde si ukážeme další vlastnosti ukazatelů.

Ukazatele a pole

Z předchozí části víme, že pokud ukazatel odkazuje na nějakou proměnnou, tak hodnotou tohoto ukazatele je právě adresa dané proměnné. Dále víme, že paměť počítače je realizována souvislou řadou očíslovaných buněk o velikosti 1B. Proto některé proměnné zaberou více buněk a jiné zase méně, v závislosti na datovém typu. Vezměme si například proměnnou typu float:

float pepe;

Proměnná tohoto typu má velikost 4B, proto zabere v paměti 4 buňky(101, 102, 103, 104):

ukazatel

Dále vytvořme ukazatel, který na tuto proměnnou bude odkazovat:

float *tom;
tom = &pepe;

Každý ukazatel, bez ohledu na to jekého je typu, má velikost 1B. To znamená, že může vždy uchovávat adresu pouze jedné buňky paměti.

Proto i v našem příkladě bude uchovávat adresu pouze jedné buňky a to i přesto, že odkazuje na proměnnou o velikosti 4B. Konkrétně to bude adresa první buňky, tedy 101.

ukazatel Znamená to tedy, že adresa proměnné odpovídá prvnímu elementu této proměnné - v tomto případě paměťové buňce.

Na stejném principu pracují také pole. Mějme například následující pole:

int adam[5];

Proměnná adam je ve skutečnosti ukazatel, který konstantně ukazuje na první prvek pole, tj. prvek s indexem nula. Proto říkáme že proměnná adam je tzv. konstantní ukazatel.

Pro lepší představu si ukážeme následující příklad:

#include <iostream>
using namespace std;
int adam[2];
int *pepe;

int main ()
{
pepe = adam;
*pepe = 777;
pepe = adam + 1;
*pepe = 999;

cout << "Prvek pole s indexem 0: " << adam[0] << endl;
cout << "Prvek pole s indexem 1: " << adam[1] << endl;
return 0;
}

V příkladě jsme deklarovali pole adam o rozměru 2 a ukazatel pepe. Pojďme si podrobně popsat hlavní funkci programu:

Hned na prvním řádku narazíme na příkaz pepe = adam;, čímž ukazatelipepe říkáme kam má odkazovat. Nyní je potřeba si uvědomit, že proměnná adam je rovněž ukazatel, který konstantně ukazuje na první prvek pole adam. Proto nepoužijeme operátor reference (&).

Příkaz pepe = adam; tedy znamená: Přiřaď ukazeteli pepe adresu na kterou odkazuje ukazatel adam.

ukazatel

Na následujícím řádku pomocí ukazatele pepe přistoupíme k prvku pole sindexem 0 a uložíme do něj hodnotu 777.

ukazatel

Dostáváme se ke třetímu řádku hlavní funkce s příkazem: pepe = adam + 1;. Tento příkaz opět uloží do ukazatele pepe adresu na kterou odkazuje ukazateladam. V tomto případě však adresu o 1 vyšší. Ukazateladam konstantně ukazuje na adresu 101. Z toho plyne že ukazatelipepe bude přiřazena adresa 101 + 1 = 102.

ukazatel

Následně opět přistoupíme k prvku pole pomocí ukazatele pepe. Tentokrát však budeme přistupovat k prvku s adresou 102 a uložíme do něj číslo 999.

ukazatel

Nakonec necháme vypsat hodnoty obou prvků pole na obrazovku:

Prvek pole s indexem 0: 777
Prvek pole s indexem 1: 999

Inicializace ukazatele

Vždy když chceme vytvořit ukazatel, tak nejprve provedeme jeho deklaraci a poté mu přiřadíme adresu nějakého elementu (provedeme inicializaci). Například:

int *pepe;
int adam;
pepe = &adam;

Deklaraci a inicializaci však můžeme provést v jednom kroku. V takovém případě ovšem musíme proměnnou na kterou se bude odkazovat, deklarovat jako první:

int adam;
int *pepe = &adam;

Ukazetele odkazující na jiné ukazatele

V jazyce C++ ukazatele nemusí nutně odkazovat pouze na proměnné, mohou totiž odkazovat i na jiné ukazatele. Podívejme se na následující příklad:

int pepe = 77;
int *adam;
int **tom;
pepe = &adam;
tom = &pepe;
cout << **tom;

První věcí, která jistě upoutá Vaši pozornost, jsou 2 hvězdičky u ukazateletom. Tento zápis nemá žádnou speciální funkci oproti tomu s jednou hvězdičkou, je však v tomto případě nazbytný, jelikož ukazatel tom je o úroveň níže než ukazateladam. Pro lepší představu se podívejme na tuto ilustraci:

ukazatel

Počet hvězdiček u ukazatele tedy určuje úroveň tohoto ukazatele. Laicky řečeno, to je vzdálenost od proměnné. Zatímco ukazatel adam je od proměnnépepevzdálen 1 krok, tak ukazatel tom je vzdálen 2 kroky -proto 2 hvězdičky. S každým dalším o úroveň nižším ukazatelem by jsme přidali další hvězdičku.

Pro ověření správnosti tohoto příkladu jsme nechali vypsat hodnotu proměnné, ne kterou odkazuje ukazatel tom. V tomto případě opět použijeme 2 hvězdičky, jako operátor dereference:

77

Ukazatel typu void

Ukazatel typu void je spaciální ukazatel, který může odkazovat na elementlibovolného datového typu. Tento ukazatel je deklarován stejně jako všechny ostaní, pouze s tím rozdílem, že místo datového typu uvedeme klíčové slovo void. Například:

void *pepe;

Tento ukazatel tedy může odkazovat na elementy libovolného typu:

void *pepe;

int adam;
char tom;
float alex;

pepe = &adam;
pepe = &tom;
pepe = &alex;

Jak můžete vidět v této ukázce, pomocí jednoho ukazatele můžeme odkazovat na proměnné o třech různých datových typech (int, char, float).

Problém však nastane ve chvíli, kdy budeme chtít pomocí operátoru dereference přistopit k hodnotě proměnné na kterou je odkazováno. Tento postup totiž povede k chybě.

To je způsobeno tím, že ukazatel neví na jaký datový typ ukazuje. Proto nemůžeme k hodnotě proměnné, na kterou je odkazováno, přistoupit. V takovém případě si budeme muset vypomoci ještě jedním ukazatelem, jehož datový typ je shodný s datovým typem proměnné.

To však ještě nebude stačit, jelikož adresu na kterou odkazuje ukazatel typu void můžeme přiřadit opět pouze ukazateli typu void. Proto budeme muset ukazatel void přetypovat na požadovaný datový typ, viz příklad:

int adam = 77;
void *pepe;
int *tom;

pepe = &adam;
tom = (int*)pepe;
cout << *tom;

Přetypování proběhne na zvýrazněném řádku. Jelikož je proměnná adam typu int, přetypujeme ukazatel pepe rovněž na typ int.

Pro ověření spávnosti necháme vypsat hodnotu, na kterou odkazuje ukazatel tom:

77

NULL ukazatel

NULL ukazatel je klasický ukazatel libovolného datového typu (ne však void), obsahující hodnotu NULL (nula), která značí, že neodkazuje na žádnou platnou adresu v paměti. Například:

int *pepe;
pepe = 0;
Pozor! Nepleťte si void ukazatel a NULL ukazatel. Zatímco void je speciální typ ukazatele, který může odkazovat na elementy libovolného datového typu, tak NULL je ukazatel libovolného datového typu, který neodkazuje na žádnou platnou adresu v paměti. Dále je důležité vědět, že NULL ukazatel je něco úplně jiného než ukazatel, který není inicializován (nemá přiřazenu adresu, na kterou má odkazovat).
C++ Návod
Úvod do C++
Volba programu
Struktura programu
Proměnné
Konstanty
Operátory
Vstup a výstup
Řídící struktury
Funkce - 1.část
Funkce - 2.část
Pole
Práce s textovými řetězci
Ukazatele - 1.část
Ukazatele - 2.část
Dynamické proměnné
Datové struktury
©2008 - 2011 Klikzone.cz
Ráj aut - inzerce nových i ojetých aut