[Přednáška 6] [Obsah] [Přednáška 8]

Přednáška 7


Témata


Uložení dvourozměrného pole v jazyce C

Dvourozměrné pole je v jazyce C uloženo jako pole polí, tedy pomocí jednorozměrných polí. Způsob uložení odpovídá uložení po řádcích. Každý řádek pole je uložen jako samostatné jednorozměrné pole. Velikost těchto polí odpovídá počtu sloupců - druhému z indexů. Ukazatele na jednotlivé řádky jsou uloženy v samostatném jednorozměrném poli, na obrázku nakresleném svisle. Ukazatel pole ukazuje na toto pole, obrázek 1:

Uložení dvourozměrného pole
Obrázek 1: Uložení dvourozměrného pole v paměti

Připomenene-li si ukazatelovou aritmetiku a princip práce s ukazateli, snadno odvodíme význam výrazů zapsaných níže:

pole+1 Hodnotou tohoto výrazu je ukazatel na druhý prvek svisle nakresleného pole.
*(pole+1) nebo pole[1] Pomocí * přistupuji k hodnotě paměťového místa, kam ukazatel ukazuje; tedy hodnotou *(pole+1) je obsah druhého prvku pole , tj. ukazatel na jednorozměrné pole představující celý druhý řádek dvourozměrného pole (modrý kroužek). Hodnotu tohoto ukazatel obržíme také jako pole[1].
*(pole+1)+4 nebo pole[1]+4 K hodnotě ukazatele na počátek druhého řádku přičítáme hodnotu 4 (posuv o 4 prvky). Hodnotou výrazu je ukazatel na poslední prvek (sloupec) druhého řádku (červeně orámovaný).
*(*(pole+1)+4) nebo pole[1][4] Hodnota červeně orámovaného prvku dvourozměrného pole.

Dynamická alokace dvourozměrného pole

Při dynamické alokaci dvourozměrného pole budeme postupovat tak, abychom dosáhli stejného způsobu uložení jako na obrázku 1. Nejprve alokujeme dynamicky pole ukazatelů na řádky (svislé pole), jehož velikost je rovna počtu řádků. Pak do každého prvku pole přiřadíme ukazatel na dynamické jednorozměrné pole (řádek) velikosti rovné počtu sloupců.

Svisle nakreslené pole v obrázku 1 je pole, jehož prvky jsou ukazatele na jiné pole. Dynamické dvourozměrné pole proto deklarujeme pomocí ukazatele na ukazatel, píšeme tedy dvě hvězdičky:

int **pole; // pole je ukazatel na ukazatel
Dynamické pole bude mít n řádek a m sloupců. Nejprve alokujeme dynamicky pole pro ukazatele na řádky:
   pole = (int **)malloc(sizeof(int*)*n);
Připomeňme, že prvky pole jsou ukazatelé na jednorozměrná pole, proto je v argumentu sizeof(int*). Dále v cyklu alokujeme pole pro jednotlivé řádky o velikosti m a ukazatele na počátek přiřadíme do prvků pole pole.
  for(int i=0;i<n;i++)
    pole[i] = (int *)malloc(sizeof(int)*m);
Nyní můžeme s polem pracovat. K prvkům lze přistupovat všemi způsoby popsanými výše.

Při dealokaci pole uvolňuje nejprve jednotlivé řádky:

  for(int i=0;i<n;i++)
    free(pole[i]);
Nakonec uvolníme pole pro ukazatele na jednotlivé řádky:
  free(pole);

Úloha 7.1

Napište program, dynamicky alokuje dvourozměrné pole pro dolní trojúhelníkovou matici o velikosti n, n je zadané číslo představující rozměr matice. Pole pro jednotlivé řádky deklarujte různě velké, přesně podle potřeb trojúhelníkové matice. Matici vyplňte čísly podle obrázku a vytiskněte na obrazovku. Nezapomeňte na uvolnění paměti v závěru programu.

Řešení:

Dev C++:trojuh_matice.dev, trojuh_matice.c
CodeBlocks:trojuh_matice.cbp, trojuh_matice.c


Dynamické dvourozměrné pole jako parametr funkcí

V případě, že chceme předat ukazatel na počátek dvourozměrného dynamického pole, deklarujeme parametr jako „ukazatel na ukazatel“. V tomto případě nelze předat jako skutečný parametr statické dvourozměrné pole, překladač hlásí chybu (např. chybu Cannot convert int[][3] to int**.). Stejný případ nastane v opačném případě, tj. je-li formálním parametrem statické pole a chceme-li předat jako skutečný parametr ukazatel na ukazatel. Vzájemné „míchání“ parametrů pomocí přetypování není možné.
float max_prvek(float pole[][3], int n)
{
  // kód
  // jako skutečný parametr mohu předat
  // libovolné statické pole, které má první
  // dimenzi libovolnou a druhou pouze 3
}
float max_prvek(float **pole, int n, int m)
{
  // kód
  // jako skutečný parametr mohu předat
  // ukazatel na dynamické dvourozměrné pole
}


[Přednáška 6] [Obsah] [Přednáška 8]