Ukazatel (datový typ)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 11. dubna 2021; kontroly vyžadují 11 úprav .

Ukazatel ( anglicky  pointer ) je proměnná, jejíž rozsah hodnot se skládá z adres paměťových buněk nebo speciální hodnoty - nulová adresa . Ten se používá k označení, že ukazatel aktuálně neodkazuje na žádnou z platných buněk. Ukazatele vynalezla Ekaterina Logvinovna Yushchenko v Address Programming Language (1955), a ne Harold Lawson v roce 1964, jak se dlouho věřilo v zahraničí [1] . V roce 1955 byly koncepty nepřímého adresování a adresování vyšších pozic zavedeny v Address Programming Language , který pokrývá koncept ukazatele a jeho rozsah v moderních programovacích jazycích.

Rozsah

Ukazatele se používají ve dvou oblastech:

Akce na ukazatele

Programovací jazyky , které poskytují typ ukazatelů, na nich zpravidla obsahují dvě základní operace: přiřazení a dereference .

V roce 1955 zavedl Address Programming Language (SSSR) „bar-operaci“ (dereferencování ukazatele), která byla hardwarově implementována F-operací procesoru v Kyjevském počítači (1955) a později v M-20. počítače , „ Dnepr “, počítače rodiny BESM (BESM-2, BESM-3, BESM-3M a BESM-4), rodiny Minsk a Ural a také některé další počítače sovětské výroby. Vícenásobné využití dereferencování ukazatelů bylo v těchto počítačích implementováno také v hardwaru pomocí operací aktualizace skupinových adres pro urychlení práce se stromovými formáty ( speciálním případem stromových formátů jsou seznamy a další abstraktní datové typy ).

První přiřadí nějakou adresu ukazateli. Druhý se používá pro přístup k hodnotě v paměti, na kterou ukazuje ukazatel. Dereferencování může být explicitní nebo implicitní; ve většině moderních programovacích jazyků dochází k dereferencování pouze tehdy, je-li výslovně uvedeno[ co? ] .

Příklad práce s ukazateli v jazyce C :

int n = 6 ; // Deklarování proměnné n typu int a přiřazení jí hodnoty 6 int * pn = malloc ( sizeof ( int ) ); // Deklarace ukazatele pn a přidělení paměti pro něj * pn = 5 ; // Dereference pointer a přiřazení hodnoty 5 n = * pn ; // Přiřaďte n hodnotě (5), na kterou ukazuje pn free ( pn ); // Uvolní obsazenou paměť pn = & n ; // Přiřadí ukazatel pn k adrese proměnné n (ukazatel bude ukazovat na n) n = 7 ; // *pn se také stalo rovno 7

Unární operátor &vrací adresu proměnné a operátor *se používá k dereferenci:

int sourceNum1 = 100 ; int sourceNum2 = 200 ; int * pNum1 = & sourceNum1 ; int * pNum2 = & sourceNum2 ; printf ( "Hodnota ukazatele 1-%d, 2-%d \n " , * pNum1 , * pNum2 ); pNum1 = pNum2 ; printf ( "Hodnota ukazatele 1-%d, 2-%d \n " , * pNum1 , * pNum2 );

Pokud ukazatel ukládá adresu nějakého objektu, pak se říká, že ukazatel odkazuje nebo ukazuje na tento objekt.

Jazyky, které umožňují použití ukazatelů pro dynamickou alokaci paměti , musí obsahovat operátor pro explicitní alokaci proměnných v paměti. V některých jazycích je kromě tohoto operátoru ještě operátor pro explicitní mazání proměnných z paměti. Obě tyto operace mají často podobu vestavěných rutin (funkce malloc a free v C, operátory new a delete v C++ a tak dále). Při použití jednoduchého ukazatele namísto inteligentního ukazatele byste měli vždy včas odstranit proměnnou z paměti, abyste se vyhnuli úniku paměti .

Ukazatel na zrušení

Ukazatel typu void vám umožňuje odkazovat na jakýkoli datový typ , včetně třídy . Tato technologie je základem jakéhokoli typu knihovny Boost .

třída A { int pole ; }; AclA ; _ void * pA = ( void * ) & clA ; // ukazatel pA odkazuje na objekt třídy A

Ukazatel na ukazatel (adresování vyšších pozic)

V programování jsou také ukazatele na ukazatele. Ukládají adresy paměti, kde jsou ukazatele na paměť, kde se nachází datový objekt, nebo jiný ukazatel. Zřetězení ukazatele na ukazatel, který opět ukazuje na ukazatel, nám umožňuje zavést koncept dereferencování více ukazatelů (v jazyce Address Programming Language : „adresování vyšších úrovní“ ) a odpovídající akci s ukazateli: Vícenásobné indirection.

int x , * p , ** q ; x = 10 ; p = & x ; q = & p ; // ukazatel na ukazatel printf ( "%d" , ** q );

Nulové ukazatele

Nulový ukazatel je ukazatel, který má speciální hodnotu, která označuje, že daná proměnná ukazatele neodkazuje (neukazuje na) žádný objekt. V programovacích jazycích je reprezentován speciální konstantou [4] :

Hlavní problémy aplikace

Ukazatele se těžko ovládají. Je dost snadné zapsat špatnou hodnotu do ukazatele, což může způsobit těžko reprodukovatelnou chybu. Například jste omylem změnili adresu ukazatele v paměti nebo nesprávně alokovali paměť pro informace a zde na vás může čekat překvapení: dojde k přepsání další velmi důležité proměnné, která se používá pouze uvnitř programu. Pochopit, kde přesně je chyba a reprodukovat ji, nebude snadné a odstranění takových chyb není vždy triviální úkol, někdy musíte přepsat významnou část programu [6] .

K vyřešení některých problémů existují metody ochrany a pojištění:

Inicializovat ukazatele

Příklad chyby s neinicializovaným ukazatelem:

/* program je neplatný. */ int main ( void ) { int x , * p ; // Alokovaná paměť pro x, ale ne pro *p x = 10 ; // Paměť se zapisuje 10 * p = x ; // 10 je zapsáno na nedefinované místo v paměti, což může způsobit selhání programu. návrat 0 ; }

V tak malém programu může problém zůstat bez povšimnutí. Ale když se program rozroste, může být náhle jasné, že proměnná je zapsána mezi jiné datové bloky, které jsou pro program důležité. Chcete-li se této situaci vyhnout, stačí inicializovat ukazatel [6] .

Používejte ukazatele správně

Nesprávné použití ukazatele:

#include <stdio.h> /* program je neplatný */ int main ( void ) { int x , * p ; x = 10 ; p = x ; printf ( "%d" , * p ); návrat 0 ; }

Volání printf()nezobrazuje na obrazovce hodnotu х, která je 10. Místo toho je na výstupu nějaká neznámá hodnota – je to výsledek nesprávného použití operátoru přiřazení ( р = х;). Tento operátor přiřadí hodnotu 10 ukazateli р, který by měl obsahovat adresu, nikoli hodnotu. Naštěstí chybu v tomto programu detekuje kompilátor – vydá varování o neobvyklé konverzi ukazatele. Pro opravu chyby napište p = &х;[6] .

Správné použití ukazatele
  • pokuste se okamžitě inicializovat proměnné při deklaraci ( int x = 10;);
  • nemíchejte ukazatele s běžnými proměnnými (jako int x, *p, y, *y_ptr;);
#include <stdio.h> int main ( void ) { int x = 10 ; int * p = & x ; printf ( "%d" , * p ); návrat 0 ; }

Únik paměti

Únik paměti  je proces nekontrolovaného snižování množství volné paměti RAM (random-access Memory) počítače spojený s chybami ve spuštěných programech, které neuvolňují nepotřebné oblasti paměti včas, nebo s chybami ve službách řízení systémové paměti.

char * ukazatel = NULL ; int i = 0 ; pro ( i = 0 ; i < 10 ; i ++ ) { ukazatel = ( char * ) malloc ( 100 ); // Paměť alokuje 10krát } zdarma ( ukazatel ); // A se uvolní pouze v posledním případě

Porovnání ukazatelů

Adresy paměti přiřazené ukazatelům lze porovnávat. Porovnání formuláře pNum1 < pNum2a pNum1 > pNum2se často používají k postupnému iterování prvků pole ve smyčce : pNum1odpovídá aktuální pozici v paměti a odpovídá pNum2 konci pole. pNum1 == pNum2vrátí hodnotu true, pokud oba ukazatele ukazují na stejné místo v paměti.

Aritmetika adresy

Aritmetika adres se objevila jako logické pokračování myšlenky ukazatelů zděděných z jazyků symbolických instrukcí: v posledně jmenovaných je možné označit určitý posun od aktuální pozice.

Typické operace aritmetiky adres:

int * p ; // Řekněme, že p ukazuje na adresu 200 p ++ ; // Po inkrementaci ukazuje na 200 + sizeof(int) = 204 p -- ; // Nyní ukazuje zpět na 200.

Chytrý ukazatel

V některých programovacích jazycích existují třídy (obvykle šablony), které implementují rozhraní ukazatele s novou funkčností, která opravuje některé z výše uvedených nedostatků.

Rejstřík v biologii člověka

Mozek používá skupiny buněk podobné ukazateli k provádění některých úkolů spojených se zapamatováním nových informací [7] .

Poznámky

  1. Videla, Alvaro Kateryna L. Juščenko - Vynálezce  ukazatelů . https://medium.com/ . Počítač vlastních průkopníků výpočetního věku (8. prosince 2018). Staženo 30. července 2020. Archivováno z originálu 23. září 2020.
  2. K čemu slouží ukazatele? . Získáno 20. února 2013. Archivováno z originálu 26. února 2013.
  3. 14.1. Alokace paměti (downlink) . - „Adresa začátku alokované paměti je vrácena do bodu volání funkce a zapsána do proměnné ukazatele. Takto vytvořená proměnná se nazývá dynamická proměnná. Získáno 22. února 2013. Archivováno z originálu 25. června 2013. 
  4. Otázka 5.1 . comp.lang.c Často kladené otázky. Získáno 20. února 2013. Archivováno z originálu 26. února 2013.
  5. Název nulového ukazatele:  nullptr . JTC1.22.32 . JTC1/SC22/WG21 – Výbor pro standardy C++ (2. října 2007). Datum přístupu: 4. října 2010. Archivováno z originálu 11. února 2012.
  6. 1 2 3 Problémy související s ukazateli . Získáno 22. února 2013. Archivováno z originálu 26. února 2013.
  7. Mozek používá programovací triky k řešení nových problémů . RIA Novosti (23. září 2013). Získáno 13. září 2016. Archivováno z originálu 20. září 2016.