Ako vytvoriť ukazovatele v jazyku C?
Ukazovatele sú nočnou morou každého nového programátora C. Sú to však tiež vlastnosti, ktoré z C urobili rozšírený a výkonný programovací jazyk, akým je dodnes. Rovnako ako mnoho ďalších programovacích funkcií a konštrukcií existuje systematický prístup k vytváraniu a používaniu ukazovateľov C. Tento článok je podrobným sprievodcom k vytváraniu a používaniu ukazovateľov jasným a jednoduchým spôsobom.
- Ukazovatele sú premenné, ktoré vo všeobecnosti obsahujú adresu pamäťového miesta (toto pamäťové miesto môže obsahovať údaje premennej alebo môže byť zatiaľ nepriradené).
- Referencie sú premenné, ktoré uchovávajú adresu pamäte inej premennej.
- Hlavný rozdiel medzi referenciou a ukazovateľom je v tom, že odkazy ukazujú na pridelené pamäťové miesta, zatiaľ čo ukazovatele môžu ukazovať na nepridelené pamäťové miesta.
- Existuje rozdiel medzi operátorom adresy (používa sa na premenných na vrátenie adresy v pamäti), operátorom referenčnej deklarácie (používa sa v referenčnej deklarácii na označenie, že deklarovaná premenná je referenciou) a bitovým operátorom „a“, všetky majú rovnaký symbol (&)
- Ukazovatele je možné zvyšovať a znižovať (čo vám umožňuje zmeniť umiestnenie, na ktoré ukazuje ukazovateľ).
- Ukazovatele je možné priradiť ktoroukoľvek z nasledujúcich metód:
- Priradenie odkazu na ukazovateľ tak, aby ukazovateľ ukazoval na rovnaké miesto v pamäti ako referencia.
- Priradenie akéhokoľvek iného ukazovateľa rovnakého typu k ukazovateľu tak, aby oba ukazovatele smerovali na rovnaké miesto.
- Priradením číselnej hodnoty ukazovateľu (v hexadecimálnom formáte) bude ukazovateľ ukazovať na konkrétne miesto v pamäti adresované touto číslicou.
- Priradenie adresy premennej typu ukazovateľa ukazovateľu, aby ukazovateľ ukazoval na miesto v pamäti prvého bajtu binárnej reprezentácie premennej v pamäti.
- Referencie možno priradiť ktoroukoľvek z nasledujúcich metód:
- Priradenie iného odkazu k odkazu.
- Priradením premennej rovnakého typu ako referencie sa referenčný bod stane premennou.
- Ukazovatele a odkazy majú dátové typy, ktoré označujú typ údajov, na ktoré ukazuje ukazovateľ/referencia.
- Typ odkazu obmedzuje priradenie tohto odkazu k premenným/odkazom rovnakého dátového typu. Ak napríklad deklarujeme celočíselný odkaz (int & d;), môžeme k nemu priradiť iba iný celočíselný odkaz alebo celočíselnú premennú (int i = 0; d = i;)
- Typ ukazovateľa obmedzuje priradenie ukazovateľa odkazom, adresám premenných/ukazovateľov rovnakého dátového typu. Má to tiež vplyv na vyhľadávanie údajov, na ktoré je odkazovaný, takže celočíselný ukazovateľ bude získavať počet bajtov rovnajúci sa počtu bajtov zaberaných celým číslom v systéme. Výber typu údajov tiež ovplyvňuje spôsob zvýšenia a zníženia ukazovateľov. Keď sa ukazovateľ zvýši, ukazuje na nasledujúcu hodnotu typu údajov z aktuálneho umiestnenia. Ak napríklad celočíselná hodnota zaberie 4 bajty v pamäti, pričom sa zvýši ukazovateľ celého čísla, bude ukazovať na ďalšie celé číslo, ktoré je 4 bajty za aktuálnym umiestnením, a tak sa hodnota samotného ukazovateľa zvýši o násobky 4.
- Názvy premenných polí sa považujú za statické/konštantné ukazovatele smerujúce na prvý bajt prvej položky v poli a majú rovnaký typ ako položky poľa.
- 1Rozhodnite o type ukazovateľa (to znamená o type údajov, na ktoré bude ukazovateľ ukazovať). Nasledujúce tipy vám môžu pomôcť:
- Ak deklarujete dynamické pole, použite typ údajov položiek poľa.
- Ak deklarujete ukazovateľ na prístup k údajom premennej, použite rovnaký typ údajov ako premennú.
- Ak deklarujete ukazovateľ na prechádzanie štruktúrou zoznamu, použite dátový typ uzla zoznamu (zvyčajne štruktúru vytvorenú používateľom).
- Ak deklarujete ukazovateľ na prechod stromom, použite ako typ údajový typ uzla stromu alebo ukazovateľ na typ uzla stromu (ukazovateľ na ukazovateľ typu uzla stromu!).
- 2Deklarujte ukazovateľ pomocou syntaxe, ako je táto: data-type * pointer-identifier; kde
- data-type je typ, ktorý ste sa rozhodli v kroku 1
- pointer-identifier je identifikátor alebo názov premennej ukazovateľa
- 3Priraďte ukazovateľ na počiatočné miesto v pamäti. To je možné vykonať jedným z nasledujúcich spôsobov:
- Prideľovanie pamäte a ukazovanie na ňu ukazovateľom: int * i = malloc (sizeof (int) * n); kde n je počet blokov pamäte, ktoré sa majú priradiť.
- Priradenie adresy premennej smerníku: int * i = & x; kde "x" je celé číslo a (&) znamená adresu.
- Priradenie identifikátora poľa k ukazovateľu: int * i = pole1; kde pole1 je celočíselné pole (int [] pole1;).
- Priradenie odkazu na ukazovateľ: int * i = a; kde „a“ je odkaz na celé číslo (int & a;).
- Priradenie iného ukazovateľa k ukazovateľu: int * i = z; kde „z“ je ďalší celočíselný ukazovateľ (int * z;)
- 4Kedykoľvek potrebujete extrahovať údajovú položku, na ktorú ukazuje ukazovateľ, použite operátor value-at-address (*): int x = *i; kde i je celočíselný ukazovateľ.
- 5Operátor indexovania použite na ukazovateli, ako keby to bolo pole, kedykoľvek chcete získať miesto v pamäti vedľa ukazovateľa bez toho, aby ste ukazovateľ v skutočnosti posunuli. Ak máte napríklad celočíselný ukazovateľ i, môžete použiť i [2], ktorý vyhľadá celé číslo, ktoré je za celým číslom bezprostredne za celým číslom, na ktoré odkazuje odkaz (celé číslo, ktoré je 2 celé číslo za aktuálnym umiestnením). Ukazovateľ i bude stále ukazovať na rovnaké miesto v pamäti. Ďalšou alternatívou je získanie hodnoty na ukazovateli 2 kroky za týmto ukazovateľom: *(i + 2)
- 6Kedykoľvek potrebujete zmeniť aktuálne umiestnenie, použite operátory prírastku (++), zníženia (-),+= a - =. i += 5; posunie celočíselný ukazovateľ i o 5 celých čísel dopredu.
- 7Po dokončení pomocou kurzora, ak máte pridelené spomienku na tento ukazovateľ, aby sa, že ste uvoľniť pridelené pamäte pomocou bezplatnej funkcie (). (zadarmo (i); kde i je ukazovateľ)
- Keď deklarujete ukazovateľ ako člena štruktúry, získate prístup k ukazovateľu samotnému pomocou operátora bodka (.) A k hodnote, na ktorú ukazuje ukazovateľ, získate prístup pomocou operátora (*). Ak máte napríklad štruktúru s1, ktorá má celočíselný ukazovateľ c, a deklarovali ste premennú s (struct s1 s;), sc pristúpi k samotnému ukazovateľu (sc = & i), *sc získa prístup k údajom, na ktoré ukazuje podľa člen c (j = * sc).
- Ak máte štruktúru, ktorú ste alokovali pomocou malloc (), ktorá vracia ukazovateľ na štruktúru, odkazy na členy alokovanej štruktúry sa robia pomocou operátora ->. Za predpokladu, že štruktúra s1 znova a s bola deklarovaná ako ukazovateľ na tento typ štruktúry, nasledovné by priradilo adresu premennej a odkazovalo na premennú: s-> c = & j; k = *s-> c. Niektorí programátori sa kvôli zrozumiteľnosti rozhodli písať *(s-> c), aj keď to nie je potrebné.
- Pozrite sa do smetiara Boehm. Hneď po inštalácii ho môžete použiť vložením gc.h a nahradením súboru malloc () gc_malloc (). Použitie odpadkového koša znižuje chyby pamäte, ale v závislosti od programu môže zvýšiť alebo znížiť výkon.
- Zvážte použitie nástrojov na ladenie, ako je napríklad valgrind (Linux), ktoré môžu pomôcť identifikovať úniky pamäte a vysledovať používanie ukazovateľov na údaje „mimo hranice“.
- Obvykle je najlepšie nechať ukazovateľ smerujúci na akúkoľvek alokovanú pamäť, aby ste ju mohli neskôr uvoľniť.
- Je dobrou programovacou praxou, aby ste skontrolovali, či sa malloc () podarilo prideliť príslušný blok pamäte kontrolou, či sa vrátený ukazovateľ nerovná NULL alebo 0.
- Použitie operátora indexovania na ukazovateľoch môže byť nebezpečné, pretože sa môžete pokúsiť získať prístup k miestam v pamäti, ktoré nie sú povolené, alebo získať hodnoty neprideleného umiestnenia pamäte.
- Nezabudnite uvoľniť všetku pridelenú pamäť pomocou malloc (). V opačnom prípade môže dôjsť k zlyhaniu, pretečeniu pamäte a ďalším problémom vo vašom programe.
- Ukazovateľu nepriraďujte miesto v priamej pamäti (podľa adresy), pokiaľ to skutočne nie je potrebné.
- Pred použitím vždy inicializujte ukazovatele, pretože „divoké“ ukazovatele smerujú k náhodným adresám a prístup k nim poškodí váš program.
Otázky a odpovede
- Ako sú ukazovatele funkcií reprezentované v C?Sú reprezentované pomocou premennej typu (return_type (*variable_name)) (param1_type, param2_type) v kóde C. Chovajú sa ako každý iný ukazovateľ, ibaže ich možno nazvať.