V C jdou pole a ukazatele ruku v ruce. Bez pochopení jejich vztahů nemůžete napsat efektivní kód. Zvládnout to chce čas. Ale odměna – okamžitá kontrola paměti – přichází okamžitě.
Podívejme se na základní příklad. Deklarujete dvě celočíselná pole o velikosti deset.
Zkuste tento kód zkompilovat. Nepřeloží se. Jedno pole nelze přiřadit druhému pomocí znaménka rovná se. C nepodporuje kopírování datových bloků prostřednictvím příkazů přiřazení. Chcete-li zkopírovat a do b, musíte projít každý prvek.
Tuto smyčku byste mohli zkomprimovat do jednoho řádku pomocí čárky, ale to by bylo méně čitelné. Standardním přístupem je použití funkce memcpy z hlavičkového souboru string.h. Efektivně provádí kopírování byte po byte.
Selhání přiřazení b=a odhaluje základní pravidlo. V C nejsou proměnné pole samy o sobě pole. Jedná se o pevné ukazatele. a a b jsou konstantní identifikátory, které ukazují na počáteční adresu jejich paměťových bloků. a ukazuje na „a[0]“. b ukazuje na „b[0]“. Tyto adresy jsou neměnné. Název proměnné nelze přesměrovat na jiné místo v paměti. To je důvod, proč se zadání nezdaří. Kompilátor považuje název pole za konstantní ukazatel.
Protože název je v podstatě ukazatel, můžete pro přístup k datům použít aritmetiku ukazatele. Zde se syntaxe stává mocným nástrojem.
Zde je p proměnná ukazatele. Proměnnou p můžete přiřadit adresu pole a. Výraz p=a zkopíruje adresu. Nyní p obsahuje stejnou hodnotu jako název pole a. Dereferencování p pomocí *p vrátí první prvek. Výstup bude nulový.
Toto rozlišení je důležité, protože ukazatelové proměnné lze upravit. Pomocí aritmetiky můžete přinutit p, aby ukazovalo na a[1] nebo a[5]. Samotný název pole zůstává pevný na začátku. Tato flexibilita umožňuje funkcím procházet pamětí bez kopírování velkých datových struktur. To je základ nízkoúrovňového výkonu v C.
Pochopení tohoto spojení zabrání jemným chybám. Vysvětluje, proč některé funkce přijímají ukazatele místo syntaxe pole. Objasňuje strukturu paměti. Tyto znalosti zanedbávejte a budete se potýkat s chybami segmentace nebo neúmyslným přepsáním dat. Zvládněte to a uvidíte, co přesně stroj dělá.
Syntaxe se může na první pohled zdát neobvyklá. Dvojí význam hranatých závorek a hvězdiček začátečníky mate. Ale když se model vyjasní, abstrakce zmizí. Zůstávají pouze adresy a hodnoty. Nic víc.
Stojí to za námahu? Kód je rychlejší. Sníží se spotřeba paměti. Získáte přímý přístup k operacím na úrovni zařízení. Většina programů C spoléhá
Proměnnou pole můžete přímo přiřadit ukazateli, protože pod kapotou jsou v podstatě totéž.
p=a; nefunguje kvůli magii, ale protože se a rozpadne na ukazatel. Konkrétně ukazuje na paměťovou adresu prvního prvku pole (s indexem 0). Protože tento prvek je celé číslo, a funguje jako ukazatel na jediné celé číslo. Deklarování p jako ukazatel na celé číslo a přiřazení hodnoty a jednoduše dává dvěma proměnným sdílenou adresu. Místo toho můžete napsat p=&a[0];. Výsledek bude identický.
Jakmile je p připojeno k začátku a, můžete se pohybovat. Názvy polí jako a jsou konstanty; Jedná se o pevné adresy, které nelze změnit. Ukazatele jako p se chovají jinak. Můžete je pohybovat pomocí aritmetiky ukazatele.
Tady C ukazuje svou vynalézavost.
Když napíšete p++;, kompilátor k adrese nepřidá jen jeden bajt. Ví, že p ukazuje na celé číslo. Místo toho přidá sizeof(int) bajtů a zasáhne přesně další prvek. Pokud by p ukazovalo na strukturu o délce 100 bajtů, p++ by posunulo ukazatel dopředu o 100 bajtů. C dělá všechny výpočty za vás. Jednoduše pohnete ukazatelem.
Kopírování polí bez indexů
Pomocí těchto ukazatelů můžete zkopírovat jedno pole do druhého. Místo standardní smyčky s indexy:
Můžete použít ukazatele:
Je to podrobné. Dá se komprimovat.
Nebo vše zkomprimujte do jednoho řádku.
To je místo, kde operátoři dělají těžkou práci. Operátor * má vyšší prioritu než ++, ale po přírůstku dojde po přijetí hodnoty. Takže *p++ získá aktuální hodnotu a poté přesune ukazatel. *q++ dělá totéž pro cíl. Mezi těmito akcemi dochází k přiřazení. Je kompaktní. Je to rychlé. Ale je také snadné jej špatně přečíst, pokud si nedáte pozor.
Nebezpečná zóna
Co se stane, když z pole vyjmete p nebo q?
C tě nezastaví.
Kompilátor předpokládá, že víte, co děláte. Bude pokračovat ve zvyšování ukazatelů a kopírování dat do paměti, která nepatří do pole. Ostatní proměnné můžete přepsat. Můžete zaneřádit hromadu. Můžete způsobit selhání programu později na místě, které s chybou nesouvisí.
To je důvod, proč se kontrola hranic v C provádí ručně. Jazyk vám důvěřuje. Když překročíte pravidla, zaplatíte cenu.
Předávání polí funkcím
Pole můžete funkcím předat dvěma způsoby. Vypadají jinak, ale chovají se podobně.
Zvažte funkci, která vydává pole:
Nebo verze s ukazateli:
Je vyžadován parametr nia (počet prvků v poli). Pole v C neukládají svou velikost s sebou. Funkce musí vědět, kdy se zastavit.
V obou případech předáváte ukazatel na začátek pole, nikoli








































