Toggle menu
Toggle preferences menu
Toggle personal menu
Neprihlásený/á
Your IP address will be publicly visible if you make any edits.
Bez shrnutí editace
Bez shrnutí editace
Riadok 228: Riadok 228:
== Referencie ==
== Referencie ==
[[Kategória:Programovací jazyk C]]
[[Kategória:Programovací jazyk C]]
<references />{{Téma|Oblast=Kategória:Programovací jazyk C|Poradie=20}}
<references />{{Téma|Oblast=Kategória:Programovací jazyk C|Poradie=30}}

Verzia z 19:13, 2. november 2024

Ako môžeme uložiť nejakú hodnotu v jazyku C pre neskoršie použitie? Pre tento účel slúžia premenné, pomocou ktorých môžeme uložiť nejakú hodnotu ktorú chceme neskôr použiť, prípadne ak chceme uložiť nejaký výpočet a použiť ho viackrát bez toho, aby sme museli algoritmus výpočtu zakaždým opakovať.


Identifikátory v jazyku C

V jazyku C identifikátory predstavujú akúkoľvek premennú, konštantu, funkciu a jej parametre, typ, selektor, položku štruktúrovaných typov a podobne. Identifikátor je postupnosť písmen anglickej abecedy, arabských číslic a/alebo podčiarkovníka (_).

Identifikátory nemôžu obsahovať medzere alebo iné špeciálne znaky, diakritiku a podobne - prípustné sú iba znaky ASCII kódu. Pre lepšiu čitateľnosť sa používa pre oddelenie viacslovných identifikátorov podľa konvencie podčiarkovník, napr.: toto_je_moja_premenna (ale nikto nikomu neodtrhne hlavu, ak použije camelCase alebo inú konvenciu pre názvy identifikátorov).

Ako identifikátor nie je možné použiť iba jedno z nasledujúcich kľúčových slov a nič iné (jedná sa o vyhradené slová pre kompilátor jazyka C):

auto        enum        short
break       extern      signed
case        float       sizeof
char        for         static
const       goto        struct
continue    if          switch
default     inline      typedef
do          int         union
double      long        unsigned
else        register    void
entry       restrict    volatile
for         return      while

Identifikátory premenných

Identifikátor premennej predstavuje jej názov - ako označíme naše dáta tak aby sme ich vedeli neskôr použiť? Pravidlá pre voľbu identifikátoru (názvu) pre premennú sú rovnaké ako všeobecné pravidlá vyššie.

Dátové typy

Ak chceme vytvoriť nejakú premennú v jazyku C, musíme najskôr poznať jej dátový typ. Je to spôsob, ktorý definuje ako je obsah premennej uložený v operačnej pamäti (RAM). Ak chceme napríklad uložiť hodnotu, ktorá reprezentuje pozíciu znaku v ASCII tabuľke, použijeme typ char. Pre desatinné čísla použijeme float, a podobne. Je dôležité vyberať správne dátové typy - napríklad, desatinné číslo nie je možné uložiť v pamäti ako celé číslo (s tým, že takéto číslo by sa dalo používať a robilo by to, čo očakávame).

Prehľad dátových typov

Medzi základné dátové typy patria:

Kľúčové slovo

pre definíciu

Rozsah (vrátane) Povoľuje negatívne hodnoty? Koľko bitov zaberá v pamäti? Využitie
char -128 až 127 áno 8 Používame ho pre uchovávanie znakových hodnôt, pretože reprezentuje práve jeden znak v ASCII tabuľke (sám o sebe ale nepredstavuje reťazec viacerých znakov!).
unsigned char 0 až 255 nie 8 Vo veľmi špecifických prípadoch (pozri nižšie).
short -32 768 až

32 767

áno 16 V špecifických prípadoch, ak potrebujeme dodatočnú kontrolu nad využívaním pamäte RAM (napríklad, ak vyvíjame softvér pre prostredie s malým množstvom využiteľnej pamäte)[1].
unsigned short 0 až 65 535 nie 16 Vo veľmi špecifických prípadoch (pozri nižšie).
int -2 147 483 648 až

2 147 483 647

áno 32 V prevažnej väčšine prípadov, keď chceme reprezentovať celočíselnú hodnotu (v aritmetických výpočtoch, pre indexy v cykloch a podobne).
unsigned int 0 až

4 294 967 295

nie 32 Vo veľmi špecifických prípadoch (pozri nižšie).
long long -9 223 372 036 854 775 808 až

9 223 372 036 854 775 807

áno 64 Ak potrebujeme reprezentovať veľmi veľké čísla, kde je int nedostatočný.

Poznámka: zaberá 64 bitov, na 32-bitových systémoch sa "zlepia" dve 32-bitové adresy dokopy.

unsigned long long 0 až

18 446 744 073 709 551 615

nie 64 Vo veľmi špecifických prípadoch (pozri nižšie).

Poznámka: zaberá 64 bitov, na 32-bitových systémoch sa "zlepia" dve 32-bitové adresy dokopy.

float -3.4 × 1038 až 3.4 × 1038 áno 32 Ak potrebujeme vo všeobecnosti uložiť nejaké desatinné číslo.
double -1.7 × 10308 až 1.7 × 10308 áno 64 Ak potrebujeme uložiť desatinné číslo, na ktoré float nepostačuje.

Poznámka: zaberá 64 bitov, na 32-bitových systémoch sa "zlepia" dve 32-bitové adresy dokopy.

Kedy použiť signed alebo unsigned?

Hlavný rozdiel medzi signed a unsigned číslami je v tom, že signed čísla môžu byť negatívne (< 0), ale unsigned nemôžu. Pomenovanie pochádza (samozrejme) z angličtiny, kde sa znamienko negácie označuje ako "negation sign" - samotné znamienko je "sign", a teda premenné ktoré sú signed by sa dali preložiť ako "oznamienkované" (so znamienkom).

Umožňujú uloženie čísiel v väčším rozsahom, pretože bit ktorý získame navyše namiesto znamienka sa použije pre zväčšenie rozsahu (keďže môžeme kombinovať jeden bit navyše, a tým pádom uložiť väčšie čísla). Nevýhoda ale je, že počet využitých bitov v pamäti sa neredukuje a vo všeobecnosti iba zamieňame väčší rozsah s možnosťou ukladať negatívne čísla (teda, nemôžme ich použiť s úmyslom znížiť pamäť, ktorú náš program používa). Nie sú taktiež vhodné pre indexy, ako by sa na prvý pohľad mohlo zdať[2].

Sú preto vhodné iba v niekoľkých špecifických prípadoch:

  • ak pracujeme s bitmi a bitovými operáciami
  • ak sme zúfalí a potrebujeme vyšší rozsah pre uloženie nášho čísla
  • ak využívame ich vlastnosti v iných špecifických prípadoch, napríklad v kryptografii, atď...

V skratke, je lepšie o nich moc nepremýšľať pretože v kontexte bežných programovacích problémov nie sú výhodné a benefity ktoré poskytujú sú zatienené ich slabými stránkami.

boolean?

🤔

A kde je boolean?

Premenná typu boolean nie je v jazyku C definovaná. Namiesto toho sa pre reprezentáciu hodnôt pravda a nepravda používajú celočíselné konštanty 0 a 1.

Typ bool si môže definovať používateľ sám alebo zahrnúť hlavičkový súbor <stdbool.h> - ale o tom neskôr. Dovtedy budeme používať nuly a jednotky, tak ako to C od nás očakáva :)

Definícia premenných

Premenné môžeme v kóde zadefinovať jednoducho priradením vhodného dátového typu a identifikátora premennej. Ak je to potrebné, môžeme premennej ihneď priradiť aj počiatočnú hodnotu. Napr.:

int nieco;     // definícia bez počiatočnej hodnoty: ešte nevieme, čo premenná obsahuje
int cislo = 1; // definícia s počiatočnou hodnotou: priradili sme premennej hodnotu 1

Teraz môžme s číslom vykonať matematické operácie. Napríklad si môžeme zadefinovať niekoľko ďalších premenných a realizovať výpočty v rámci jednoduchého programu:

#include <stdio.h>

int main() {
    int a = 0, b = 1, c = 2; // viacnásobné priradenie, pre všetky premenné sa použije dátový typ definovaný úplne vľavo
    int vysledok = a + b * c - (c - a) / 2; // 0 + 1 * 2 - ((2 - 0) / 2) = 2 - 1 = 1
    printf("Výsledok je: %d\n", vysledok); // Výsledok je: 1

    return 0;
}

Pamäťové triedy

Definícia pamäťovej triedy určuje spôsob, akým by premenná mala byť uložená v pamäti. Vo väčšine prípadov nemusíme pamäťové triedy bližšie špecifikovať, pretože kompilátor priradí premennej vhodnú pamäťovú triedu v závislosti od kontextu v ktorom ju používame.

Napriek tomu, poznáme niekoľko pamäťových tried:

Trieda auto

Všetky lokálne premenné sú kompilátorom považované za takzvané "automatické", pokiaľ nešpecifikujeme manuálne inú pamäťovú triedu. Nie je potrebné túto pamäťovú triedu pri definícií premennej deklarovať.

Lokálne premenné sú dostupné iba v bloku kódu (scope) v ktorom boli definované, alebo v nižších (vnorených) blokoch, ak tam nie je znovu definovaná premenná s rovnakým identifikátorom. Napr.:

#include <stdio.h>

int main()
{
    int cislo = 0;
    {
        cislo = 1;
    }

    printf("číslo: %d\n", cislo); // číslo: 1
    return 0;
}

Avšak, ak premennú vo vnorenom bloku opätovne definujeme, alokujeme miesto v pamäti pre rozdielnu premennú ktorá je prístupná iba v jej bloku:

#include <stdio.h>

int main()
{
    int cislo = 0;
    {
        int cislo = 1; // Toto je iná premenná "cislo"! Jej hodnota je dostupná iba v tomto bloku
    }

    printf("číslo: %d\n", cislo); // číslo: 0
    return 0;
}

Trieda extern

Používa sa pre referencie na globálne premenné, napr.:

#include <stdio.h>

int cislo; // globálna premenná

int funkcia()
{
    extern int cislo; // referencia globálnej premennej

    return (cislo + 1);
}

int main()
{
    extern int cislo; // referencia globálnej premennej

    cislo = 1;
    int vysledok = funkcia();

    printf("číslo: %d\n", vysledok); // číslo: 2
    return 0;
}

V súčasnosti nemá táto pamäťová trieda až taký veľký význam, pretože kód v moderných kompilátoroch funguje aj bez riadku s referenciou extern.

Trieda register

Používa sa pre uloženie obsahu premennej priamo do cache procesora, čo zrýchľuje program pokiaľ nejakú premennú používame veľmi často (napr.: indexy v cykloch ktoré sa neustále zvyšujú s každou iteráciou).

Avšak, ani tu nemá vo väčšine prípadov zmysel túto pamäťovú triedu explicitne deklarovať, keďže moderné kompilátory sú dosť inteligentné na to aby napr.: premenným pre indexy v cykloch priradili triedu register automaticky.

Trieda static

Jediná trieda čo má ako-tak zmysel, avšak neodporúča sa jej časté používanie. Táto trieda alokuje pevné miesto pre nejakú premennú počas celého behu programu (je realizovaná ako pamäťová bunka). Používa sa v prípadoch, keď chceme uchovať hodnotu premennej v pamäti aj po opustení bloku. Avšak, stále sa jedná o lokálnu premennú, takže ju nemožno používať naprieč vyššími levelmi (blokmi), teda aplikujú sa rovnaké pravidlá ako tie, ktoré sme spomenuli v triede auto vyššie. Princíp je iba v tom, že obsah tejto premennej sa neodstráni z pamäte a táto pamäť zostáva pevne alokovaná počas celého behu programu (preto sa neodporúča ich používať často, môžu spôsobiť problémy so správou pamäte).

Referencie