Hledejte v chronologicky řazené databázi studijních materiálů (starší / novější příspěvky).

17. Deklarace a inicializace proměnných a polí, paměťové třídy.

Deklarace a inicializace proměnných viz otázka č. 2

Pole:
Pole je strukturovaný datový typ, což znamená, že má svou vlastní vnitřní strukturu, která je tvořena položkami určitého datového typu. K těm lze pak přistupovat odděleně.

Definice proměnné typu pole:
Proměnná typu pole se definuje podobně jako proměnná jednoduchého typu. Rozdílem je, že při definici pole se za jménem identifikátoru proměnné ještě uvádějí hranaté závorky, ve kterých určíme počet prvků pole.

bázový_typ identifikátor[počet_prvků];

Bázový_typ neurčuje typ proměnné, ale typ položek pole. Že jde o pole pozná překladač právě podle hranatých závorek. Počet_prvků je jakýkoliv konstantní výraz, tedy takový, který lze vyhodnotit již při překladu. Podívejme se na konkrétní příklad definice pole:

short int moje_pole[10];

Nadefinovali jsme proměnnou typu pole, která obsahuje 10 položek typu short int. Znamená to tedy, že se pro naši proměnnou vyhradilo 20 bytů (10 * sizeof(short int)). Tato paměť tvoří jeden souvislý blok. V případě, že je takto nadefinovaná proměnná statická (static , existuje po celou dobu vykonávání programu), jsou všechny položky pole inicializovány nulovou hodnotou. Naopak, v případě že jde o lokální automatickou proměnnou (auto , vzniká až při běhu programu a existuje pouze omezenou dobu), nejsou jednotlivé prvky pole inicializovány.
Prvky pole lze inicializovat již při definici.

Příklad:

short int moje_pole[5]={1, 0, 443, -46, 987};

V případě, že počet inicializačních výrazů je vyšší než počet položek pole, bude se při překladu hlásit chyba. Pokud je počet inicializátorů menší, chyba se nehlásí a zbylé položky jsou inicializovány buď nulovou hodnotou, nebo nejsou inicializovány vůbec.

Pokud při definici zároveň inicializujeme prvky pole, nemusíme specifikovat velikost pole, ale stačí když uvedeme prázdné závorky. Překladač sám určí velikost pole podle počtu inicializačních výrazů.

Příklad:

short int moje_pole[]={1, 0, 443, -46, 987};

Přístup k prvkům pole
Přístup k prvkům pole se provádí pomocí indexace. V jazyce C++ jsou všechny proměnné typu pole indexovány od nuly. To znamená, že první položka má vždy index 0, což není možné nijak ovlivnit.

moje_pole[0]=250;

Tímto zápisem jsme do první položky pole zapsali hodnotu 250.
S poli můžou pracovat i operátory ==, != a další, nicméně význam použití těchto operátorů je, v souvislosti s poli, jiný.

Příklad:

int moje_pole[4]={15, 35, 66, 1000};
int dalsi_pole[4]={15, 35, 66, 1000};
if (moje_pole == další_pole) {...}

I když by se mohlo zdát, že se porovnají jednotlivé prvky pole, není tomu tak. Ve skutečnosti se provede pouze porovnání ukazatelů na první prvek pole. Tyto ukazatele ale mohou být stejné pouze v případě, že půjde o identická pole a tedy blok v příkazu if v našem příkladu se neprovede nikdy, bez ohledu na položky pole.

Procházení pole
Při procházení položek pole je nutné dát si pozor na to, abychom nikdy omylem nepřekročili hranice pole. Jazyk C++ zásadně nekontroluje meze polí, a tak je bez problémů možné číst i zapisovat do paměti, která nám již nepatří. Protože se indexuje od nuly, poslední prvek pole o n položkách tedy bude mít index n-1.

Příklad:

int moje_pole[20], i;
.
.
.
for (i=0; i<20; i++) moje_pole[i]=0;

Paměťové třídy:
Modifikátory paměťové třídy
Kromě identifikátoru a datového typu jsou proměnné určeny ještě paměťovou třídou, které náleží. Paměťová třída určuje kde bude proměnná v paměti uložena, jakou bude mít viditelnost a jakou životnost.

Modifikátor auto:
Modifikátor paměťové třídy auto je implicitně používán pro všechny lokální proměnné, jejichž paměťová třída nebyla určena jiným modifikátorem. Těmto proměnným se také často říká automatické, protože paměť se pro ně alokuje automaticky až při vstupu do bloku, ve kterém jsou definovány. Po opuštění bloku je tato paměť zase uvolněna. V případě návratu do stejného bloku je místo pro proměnnou alokováno znovu, neexistuje ale žádná záruka, že to bude stejné místo jako při poslední alokaci. Stejně tak neexistuje vůbec žádná záruka, že hodnota proměnné zůstane zachována. Automatické proměnné nejsou nikdy implicitně inicializovány nulovou hodnotou. Inicializovat je musíme explicitně, například při definici proměnné. Výhodou je, že k této inicializaci není potřeba použít konstantní výraz, ale je možné inicializovat i hodnotami jiných proměnných, nebo návratovou hodnotou funkce. Automatická proměnná je viditelná jen v rámci bloku, ve kterém je definována. Existuje–li vedle této automatické proměnné i nějaká globální proměnná se stejným identifikátorem, je zastíněna automatickou proměnnou.

Příklad:

int i=10; //Globální proměnná i
auto int j; //Způsobí chybu

void fce()
{ auto int i; // Lokální proměnná i(může být napsána i bez auto)

i=20;
}

void main()
{
fce();
printf("%d", i);
return 0;
}

V uvedeném příkladu jsou definovány dvě proměnné i. První z nich je globální a druhá, definovaná uvnitř funkce fce(), je automatická lokální proměnná, která ,v oblasti své viditelnosti (uvnitř funkce), zastiňuje globální proměnnou i. Jak bude vidět z kontrolního výstupu funkce printf(), ve funkci fce() jsme skutečně pracovali s lokální proměnnou i. Definice proměnné j s modifikátorem auto vyvolá chybu, protože globální proměnné nemohou být automatické.

Modifikátor static:
Viditelnost statické lokální proměnné je shodná s viditelností automatických proměnných, tedy je viditelná jen v bloku, kde je definována. Životnost statické proměnné je ale po celou dobu vykonávání programu. Paměť pro takovou proměnnou je alokována při startu programu a uvolněna je až po jeho skončení. Z toho vyplývá, že, máme-li statickou proměnnou a opustíme blok, ve kterém byla definována, tato proměnná nezaniká, pouze již není viditelná. I tak ale lze s touto proměnnou pracovat např. pomocí ukazatele. Dojde-li k návratu do bloku s touto proměnnou, můžeme s ní znovu pracovat. Statické lokální proměnné se při definici dají inicializovat jen konstantním výrazem. Tato inicializace se ale provede jen při prvním vstupu do bloku, kde je proměnná definována. Není-li statická lokální proměnná inicializována explicitně, provede se implicitní inicializace nulovou hodnotou (opět jen při prvním vstupu do bloku).
Příklad statické lokální proměnné je zjištění kolikrát byla nějaká funkce volána:

int fce()
{ static int i=0;
return ++i;
}

void main()
{ int j;
for (j=0; j<10; j++) printf("%d ", fce());
return 0;
}

Proměnná i je při prvním zavolání funkce fce() inicializována nulovou hodnotou. Při dalším spuštění funkce se již inicializace neprovede a v proměnné i zůstává hodnota nastavená v předchozím volání funkce.

Modifikátor register:
Modifikátor register patří mezi modifikátory ovlivňující optimalizaci kódu programu. Pro zvýšení efektivnosti je totiž možné uložit některé proměnné přímo do registrů procesoru, a tak umožnit rychlejší přístup k těmto proměnným. Je ale nutné říct, že klíčové slovo register slouží spíše jen jako doporučení kompilátoru, že proměnná se hodí k uložení do registru. Jestli se tak opravdu stane, není zaručeno, už třeba kvůli omezenému počtu registrů. Na registrové proměnné také nelze aplikovat operátor reference &, a to ať už proměnná skutečně je umístěna v registru, nebo není. Životnost a viditelnost registrových proměnných je stejná jako u proměnných automatických. Modifikátor register lze aplikovat pouze na lokální proměnné, a tedy nelze definovat globální proměnnou s modifikátorem register.

Modifikátor volatile:
Druhým z modifikátorů, které ovlivňují optimalizaci, je modifikátor volatile. Pokud tímto klíčovým slovem označíme nějakou proměnnou, kompilátor ji nebude optimalizovat.

Modifikátor const:
Modifikátorem const vlastně neurčujeme paměťovou třídu, ale definujeme pomocí něho tzv. konstantní proměnné. Hodnoty takovýchto proměnných pak v programu nemůžeme přímo měnit (např. přiřazením). Jediným normálním způsobem, jak se dá hodnota konstantní proměnné nastavit, je inicializace při její definici. Pomocí ukazatelů však lze změnit hodnotu konstantní proměnné i z jiných míst programu.

Konstantní proměnné lze použít např. pro inicializaci globálních proměnných, pro definování velikostí polí, apod. jen v C++. Modifikátor const lze použít i v kombinaci s jinými modifikátory.

Příklad:

const int i=20;
int *p=&i;

i=30; //chyba, nelze provést
printf("%d\n", i);
*p=40; //nepřímá změna hodnoty konstantní proměnné
printf("%d\n", i);

Žádné komentáře:

Okomentovat