Pointery
Pointery (neboli ukazatele) slouží pro práci s adresou paměti, na které se nachází hodnota proměnné.
Představme si, že máme proměnnou i, která bude mít hodnotu 20. Deklaraci a inicializaci proměnné můžeme udělat v jednom příkazu:
int i = 20;
V momentě, kdy vytvoříme novou proměnnou, alokuje se oblast paměti (v tomto případě velikosti 4 B, protože datový typ proměnné je int) a na tom místě se bude ukládat hodnota proměnné.

S pointery jsme se v programování setkali při načítání proměnných. Funkce jako scanf() totiž vyžaduje zadat adresu, kam se bude hodnota ukládat:
scanf("%d", &x);
Stejně tak si můžeme vypsat adresu proměnné, například
int i = 20;
printf("Na adrese %p je uložena hodnota %d.\n", &i, i);
Pointery používáme jako odkazy na místo v paměti, kde je uložena hodnota proměnné, především při
- načítání hodnoty do proměnné (scanf),
- používání vstupně-výstupních proměnných ve funkcích (volání odkazem)
Deklarace pointeru
Pointer je vlastně pouze adresa prvního bytu, na které je uložena proměnná.
Deklarujeme jej pomocí typu proměnné, na kterou ukazuje v kombinaci se znakem *:
int *pa; //pointer na int
char *pc; //pointer na char
float *pf; //pointer na float
Touto deklarací jsme si pouze vytvořili pointer (ukazatel), ale ten zatím nikam neukazuje. Abychom nastavili adresu, kam bude pointer ukazovat, je potřeba provést jeho inicializaci.
Inicializace pointeru
Poté, co máme pointer deklarován, musíme říci, na jakou proměnnou bude pointer ukazovat.
Mějme například
int x = 12;
int *pint;
Abychom do pointeru pint uložili adresu proměnné x, musíme provést příkaz:
pint = &x;
Nyní v proměnné pint máme uloženou adresu, na které můžeme najít hodnotu proměnné x.

Operátory
Při práci s pointery (ukazateli) budeme tedy používat dva operátory:
- operátor hvězdička (*) = dereferenční operátor – používáme-li pointer a chceme-li se dostat na hodnotu adresy, na kterou pointer ukazuje
- operátor ampersand (&) = referenční operátor – používáme-li normální proměnnou a chceme-li získat její adresu (např. pro uložení do pointeru)
Máme-li příklad zobrazený výše, tak na hodnotu x se můžeme dostat také pomocí operátoru hvězdička:
printf("Na adrese %p je uložena hodnota %d.\n", pint, *pint);
Naopak do proměnné pint můžeme uložit adresu jiné proměnné pomocí operátoru ampersand:
int y = 25;
pint = &y;
Generovaný podcast o ukazatelích (pointerech) si můžete poslechnout zde:
Podcast byl automaticky vygenerován z této stránky a z webu https://www.geeksforgeeks.org/c/c-pointers/
Dynamické alokování velikosti pole
Když jsme začínali pracovat s polem, deklarovali jsme jej vždy pomocí pevně stanovené velikosti, například:
int znamky[5];
V tomto případě nám kompilátor alokuje 5 × 4 B paměti (za předpokladu, že pro jedno celé číslo potřebujeme 4 B). Proměnná znamky v tom případě bude vlastně pointer, který ukazuje na první prvek v daném poli.
Někdy ale dopředu nevíme, kolik prvků budeme do pole chtít uložit. Strategie použít místo čísla 5 v příkladě výše opravdu velké číslo naráží na optimální využití paměti, čili tudy cesta také nevede.
Představme si, že počet prvků pole víme až na základě nějaké proměnné, jejíž hodnotu získáme v průběhu daného programu:
//deklarace pocetZnamek už proběhla
pocetZnamek = 69;
int *znamky;
znamky = (int *) malloc(pocetZnamek * 4);
//nyní můžeme do pole znamky naplnit až 69 prvků
K dynamickému alokování paměti jsme použili funkci malloc() – zkratku z anglického memory allocation – jejímž parametrem je počet bajtů, které chceme přiřadit (v tomto případě pocetZnamek × 4, protože jeden int zabírá 4 B).
Příklady s pointery
Příklady s pointery si můžete zobrazit zde.
Příklady s pointery na webu w3resource si můžete zobrazit zde.