Začínáme programovat v jazyce C (6. díl)

V tomto díle se podíváme na pointery, pole a vícerozměrné pole.

Ukazatel, nebo-li pointer je statická celočíselná proměnná, která obsahuje adresu jiné statické nebo dynamické proměnné. Pointer nese i informace o datovém typu, který se na adrese nachází. Pointer se deklaruje pomocí operátoru dereference *.

datovy_typ *identifikator_pointeru;

Uložení adresy do ukazatele se liší podle toho, zda pointer ukazuje na dynamickou nebo statickou proměnnou. Operátorem reference & uložíme adresu statické proměnné:

identifikator_pointeru = &identifikator_promenne;

A tímto způsobem do pointeru uložíme adresu a vyalokujeme prostor pro dynamickou proměnnou:

identifikator_pointeru=(datovy_typ *)malloc(sizeof(datovy_typ));

Podívejme se nyní na tento zápis podrobněji. Funkce malloc() slouží k alokování paměťového prostoru. Jejím parametrem je počet bytů, který je potřebný pro alokaci. Počet bytů zjišťujeme operátorem pro zjištění velikosti datového typu sizeof(). Funkce malloc() vrací ukazatel na datový typ void, tak je nutné pointer přetypovat pomocí operátoru pro přetypování datovy_typ *. V případě, že se nepodaří paměť alokovat, vrací funkce hodnotu NULL, takže můžeme provést následující ošetření, zda alokace proběhla:

if (identifikator_pointeru == NULL) printf("Chyba alokace\n");

Pro uložení hodnoty na místo, na které ukazuje pointer se používá tento zápis:

*identifikator_pointeru = hodnota;

Pokud použijeme pointer na dynamickou proměnnou, tak se musíme po ukončení práce s pointerem postarat o uvolnění paměti:

free (identifikator_pointeru);

Potom také musíme vyřešit, aby pointer neodkazoval na neexistující místo:

identifikator_pointeru = NULL;

Pomocí pointerů můžeme realizovat funkce, které navracejí více hodnot.

Pole je strukturovaný homogenní datový typ. V normální řeči můžeme říct, že obsahuje několik prvků stejného datového typu, se kterými můžeme pracovat. Pole je vlastně pointer, který obsahuje adresu nultého prvku pole. Pole může být statické i dynamické.

U statického pole je potřeba znát počet prvků během překladu, deklarujeme jej takto:

datovy_typ identifikator[pocet_prvku];

Pole může nabývat hodnot jakéhokoliv základního datového typu. K jednotlivým hodnotám pole přistupujeme prostřednictvím indexu. Jazyk C indexuje od nuly, takže k prvkům přistupujeme od indexu 0 až do indexu n – 1, kde n je počet prvků pole.

Hodnoty pole jsou pod jednotlivými indexy ukládány v paměti za sebou.

POZOR: MUSÍME SI ZAPAMATOVAT, ŽE PŘEKLADAČ JAZYKA C NEPROVÁDÍ KONTROLU MEZÍ POLE, TEDY MŮŽEME PRACOVAT S INDEXY POLE, KTERÉ JSOU VĚTŠÍ NEŽ NÁMI DEFINOVANÝ NEJVYŠŠÍ INDEX. MŮŽEME TEDY PRACOVAT I S ČÁSTMI PAMĚTI, KTERÉ NEBYLY ALOKOVÁNY!

Pole je možné při deklaraci ihned inicializovat a to následovně:

datovy_typ identifikator[pocet_prvku] = { hodnota1, hodnota2, ..., hodnotan };

Určitě také budeme někdo chtít pole setřídit, zde je nejpoužívanější algoritmus:

void bubble(int p[],int n);
/* trideni pole vymenou - bubblesort */
{
   int i,j;
   int x;			        /* pomocna promenna pro vymenu */
   for (i=1; i<n; i++)			/* v 1. pruchodu se dostane nejmensi prvek nahoru */
   {
       for (j=n-1; j>=i; j--)
       {
          if (p[j-1] > p[j])		/* inverze - provede se vymena */
          {
              x = p[j-1];
              p[j-1] = p[j];
              p[j] = x;
          }
       }
    }
}

U dynamického pole není potřeba znát během překladu počet prvků, můžeme je alokovat až při běhu programu. Při překladu však musíme znát bázový typ pole. Dynamické pole deklarujeme takto:

datovy_typ *identifikator;
identifikator=(datovy_typ *)malloc(sizeof(datovy_typ)*pocet_prvku);

Práce s dynamickým polem je shodná s prací se statickým polem. Dynamické pole však musíme stejně jako dynamickou proměnnou uvolnit:

free(identifikator);

A zakotvit:

identifikator = NULL;

Je li proměnná typu pole parametrem funkce, tak užíváme adresu pole – volání odkazem a to proto, aby se hodnota pole zachovala i po návratu z funkce. Jako další parametr funkce také musíme zavést počet prvků pole, která slouží pro kontrolu mezí.

Nyní se podíváme na vícerozměrná pole. Jedná se vlastně o pole polí.

datovy_typ id_matice[radky][sloupce];

Inicializace se provádí takto:

id_matice[][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12},...};

Uvedení počtu sloupců je povinné, uvedení počtu řádků je nepovinné.

Myslím, že toto začátečníkovi stačí o vícerozměrných polích vědět a je docela zbytečné jej seznamovat s dynamickými vícerozměrnými poli (maticemi) a s použitím ve funkcích. Pokud by však byl zájem, můžeme tuto problematiku doplnit.

Příště seriál zakončíme povídáním o řetězcích, odvozených datových typech a souborech. Doufám, že jste tento díl dočetli až do konce, neboť dnes byl opravdu vyčerpávající.

O Martin Pitřík

Zajímám se o jazyk C, C++ a C#. V současné době stojím za vznikem projektu ElMetr, který si klade za cíl vytvořit program pro elektroniku zcela zdarma.