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
 
(5 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 1: Riadok 1:
Ako môžeme uložiť nejakú hodnotu v jazyku C pre neskoršie použitie?
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ť.


{{Pojmová mapa}}
{{Pojmová mapa}}
Premenné sa používajú preto, aby sme uložili 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 ==
== Identifikátory v jazyku C ==
Riadok 26: Riadok 24:


=== Identifikátory premenných ===
=== 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ť?
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 ==
== Dátové typy ==
Riadok 139: Riadok 137:
Premenná typu <code>boolean</code> nie je v jazyku C definovaná. Namiesto toho sa pre reprezentáciu hodnôt pravda a nepravda používajú celočíselné konštanty <code>0</code> a <code>1</code>.
Premenná typu <code>boolean</code> nie je v jazyku C definovaná. Namiesto toho sa pre reprezentáciu hodnôt pravda a nepravda používajú celočíselné konštanty <code>0</code> a <code>1</code>.


Typ <code>bool</code> si môže definovať používateľ sám alebo zahrnúť hlavičkový súbor <code><stdbool.h></code> - ale o tom neskôr. Dovtedy budeme používať nuly a jednotky, tak ako to C od nás očakáva :){{Téma|Oblast=Kategória:Programovací jazyk C|Poradie=20}}
Typ <code>bool</code> si môže definovať používateľ sám alebo zahrnúť hlavičkový súbor <code><stdbool.h></code> - 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.:<syntaxhighlight lang="c">
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
</syntaxhighlight>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:<syntaxhighlight lang="c" line="1">
#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;
}
 
</syntaxhighlight>
 
== Skrátené zápisy pre sčítanie a odčítanie ==
Pre číselné premenné môžeme využiť dva skrátené formy zápisov:
 
* Prechod na predošlí / nasledovný prvok: <code>premenna--</code>, <code>premenna++</code>;
* Pridanie / odobratie číselnej hodnoty: <code>premenna += 10</code>, <code>premenna -= 5</code>
 
Napr.:<syntaxhighlight lang="c" line="1">
#include <stdio.h>
 
int main() {
    int a = 10, b = 20;
    a--; // 9
    b += 10 // 30
    b -= 1 // to isté ako b--, hodnota bude 29
    printf("a: %d, b: %d\n", a, b); // a: 9, b: 29
 
    return 0;
}
 
</syntaxhighlight>
 
== Lokálne a globálne premenné ==
V C platí, že všetky premenné deklarované vrámci nejakého bloku (funkcie alebo zloženého výrazu) sú lokálne a všetky premenné deklarované mimo funkcií (zvyčajne na začiatku súboru) sú globálne.
 
Lokálne premenné sú prístupné iba v rámci bloku, v ktorom boli definované, napr.:<syntaxhighlight lang="c" line="1">
#include <stdio.h>
 
int main() {
    {
        int lokalna = 10; // platí iba pre tento blok (zložený výraz pomocou zátvoriek: {...} )
    }
 
    printf("%d", lokalna);  // Toto by bola chyba, pretože lokalna nie je v rámci tohto bloku definovaná
    return 0;
}
 
</syntaxhighlight>Globálne premenné sú dostupné naprieč celým súborom (prípadne aj externe naprieč súbormi, pri použití pamäťovej triedy <code>extern</code>, pozri nižšie):<syntaxhighlight lang="c" line="1">
#include <stdio.h>
 
int globalna = 20;  // globálna premenná
 
int main() {
    printf("Globálna premenná: %d\n", globalna); // 20
 
    {
        globalna += 10;  // zmeníme ju
    }
 
    printf("Globálna premenná: %d\n", globalna); // 30
    return 0;
}
 
</syntaxhighlight>
 
== Pamäťové triedy ==
{{Box
| text = Táto sekcia obsahuje koncepty, ktoré ešte neboli vysvetlené, ako napríklad funkcie.
<br/>
Napriek tomu táto téma patrí do premenných, preto je vhodné ju aspoň okrajovo načrtnúť.
| emoji = ⚠️
}}
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 <code>auto</code> ===
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.:<syntaxhighlight lang="c" line="1">
#include <stdio.h>
 
int main()
{
    int cislo = 0;
    {
        cislo = 1;
    }
 
    printf("číslo: %d\n", cislo); // číslo: 1
    return 0;
}
</syntaxhighlight>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:<syntaxhighlight lang="c" line="1">
#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;
}
</syntaxhighlight>
 
=== Trieda <code>extern</code> ===
Používa sa pre referencie na globálne premenné naprieč súborom alebo viacerými súbormi, napr.:<syntaxhighlight lang="c" line="1">
#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;
}
 
</syntaxhighlight>
=== Trieda <code>register</code> ===
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 <code>register</code> automaticky.
 
=== Trieda <code>static</code> ===
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 <code>auto</code> 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 ==
[[Kategória:Programovací jazyk C]]
[[Kategória:Programovací jazyk C]]
<references />{{Téma|Oblast=Kategória:Programovací jazyk C|Poradie=30}}

Aktuálna revízia z 10:25, 3. 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;
}

Skrátené zápisy pre sčítanie a odčítanie

Pre číselné premenné môžeme využiť dva skrátené formy zápisov:

  • Prechod na predošlí / nasledovný prvok: premenna--, premenna++;
  • Pridanie / odobratie číselnej hodnoty: premenna += 10, premenna -= 5

Napr.:

#include <stdio.h>

int main() {
    int a = 10, b = 20;
    a--; // 9
    b += 10 // 30
    b -= 1 // to isté ako b--, hodnota bude 29
    printf("a: %d, b: %d\n", a, b); // a: 9, b: 29

    return 0;
}

Lokálne a globálne premenné

V C platí, že všetky premenné deklarované vrámci nejakého bloku (funkcie alebo zloženého výrazu) sú lokálne a všetky premenné deklarované mimo funkcií (zvyčajne na začiatku súboru) sú globálne.

Lokálne premenné sú prístupné iba v rámci bloku, v ktorom boli definované, napr.:

#include <stdio.h>

int main() {
    {
        int lokalna = 10; // platí iba pre tento blok (zložený výraz pomocou zátvoriek: {...} )
    }

    printf("%d", lokalna);  // Toto by bola chyba, pretože lokalna nie je v rámci tohto bloku definovaná
    return 0;
}

Globálne premenné sú dostupné naprieč celým súborom (prípadne aj externe naprieč súbormi, pri použití pamäťovej triedy extern, pozri nižšie):

#include <stdio.h>

int globalna = 20;  // globálna premenná

int main() {
    printf("Globálna premenná: %d\n", globalna); // 20

    {
        globalna += 10;  // zmeníme ju
    }

    printf("Globálna premenná: %d\n", globalna); // 30
    return 0;
}

Pamäťové triedy

⚠️
Táto sekcia obsahuje koncepty, ktoré ešte neboli vysvetlené, ako napríklad funkcie.


Napriek tomu táto téma patrí do premenných, preto je vhodné ju aspoň okrajovo načrtnúť.

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é naprieč súborom alebo viacerými súbormi, 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;
}

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