Lekce 4 - Typový systém v céčku podruhé: Datové typy
V předešlém cvičení, Řešené úlohy k 1.-3. lekci Céčka, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
Nyní se na datové typy podíváme více zblízka a vysvětlíme si, kdy jaký použít. Dnešní tutoriál bude hodně teoretický, ale o to více bude praktický ten příští. Na konci si vytvoříme pár jednoduchých ukázek.
Pozn.: Velikosti a přítomnost některých datových typů se může někdy různit podle zvoleného standardu céčka a cílové architektury počítače.
Celočíselné datové typy
Podívejme se nyní na tabulku vestavěných celočíselných datových typů
v Céčku. Všimněte si typu int, který již známe z minulé
lekce.
| Datový typ | Rozsah | Velikost | 
|---|---|---|
| char | -128 až 127 | 8 bitů | 
| short | -32 768 až 32 767 | 16 bitů | 
| int | -32 768 až 32 767 nebo -2 147 483 648 až 2 147 483 647 | 16 nebo 32 bitů (běžně 32 bitů) | 
| long int | -2 147 483 648 až 2 147 483 647 | 32 bitů | 
| long long int | -9 223 372 036 854 775 808 až 9 223 372 036 854 775 807 | 64 bitů | 
Poznámka: U velikostí datových typů záleží na operačním systému, tedy zda je 16 bitový nebo 32/64 bitový. Pro vás budou platit obvykle ty vyšší hodnoty.
Možná si teď říkáte, že je divné, že char je číslo,
když jsme ho uvedli jako znak v předchozích dílech. My však můžeme
char použít jako číslo a zároveň jako znak (při výpisu buď
použijeme %d jako číslo a nebo %c jako znak). Je to
proto, že znaky jsou ve skutečnosti uloženy jako jejich číselné kódy,
tzv. ASCII hodnoty.
Další otázka, která vás asi napadá, je: Proč máme tolik možných
typů pro uložení čísla? Odpověď je prostá - záleží na jeho velikosti.
Čím větší číslo, tím více spotřebuje paměti. Pro věk uživatele tedy
můžeme zvolit char, protože se asi nedožije více, než
127 let. Představte si databázi milionu uživatelů nějakého
systému. Když zvolíme místo charu int, bude
zabírat 4x (nebo 2x) více místa. Naopak, když budeme mít funkci k výpočtu
faktoriálu, stěží nám bude stačit rozsah typu int a
použijeme long int.
Nad výběrem datového typu nemusíte moc přemýšlet a většinou se
používá jednoduše int. Typ řešte pouze v případě, když
jsou proměnné v nějakém poli (obecně kolekci) a je jich tedy více, potom
se vyplatí zabývat se paměťovými nároky. Tabulky sem dávám spíše pro
úplnost.
Desetinná čísla
U desetinných čísel je situace poněkud jednodušší, máme na výběr
pouze dva datové typy. Samozřejmě se opět liší v rozsahu hodnot, dále
však ještě v přesnosti (vlastně počtu des. míst). Typ double
má již dle názvu dvojnásobnou přesnost oproti float.
| Datový typ | Rozsah | Přesnost | Velikost | 
|---|---|---|---|
| float | 1.2E-38 to 3.4E+38 | 6 číslic | 32 bitů | 
| double | 2.3E-308 to 1.7E+308 | 15 číslic | 64 bitů | 
| long double | 3.4E-4932 to 1.1E+4932 | 19 číslic | 80 bitů | 
Pozor, vzhledem k tomu, že desetinná čísla jsou v počítači
uložena ve dvojkové soustavě, dochází k určité ztrátě přesnosti.
Odchylka je sice téměř zanedbatelná, nicméně když budete programovat
např. finanční systém, nepoužívejte tyto datové typy pro uchování
peněz, mohlo by dojít k malým odchylkám. Velikost long double
se může lišit dle implementace.
Když do float chceme dosadit přímo ve zdrojovém kódu, měli
bychom použít suffix f, u double sufix nepíšeme,
jakékoli desetinné číslo ve zdrojovém kódu bez suffixu f je
bráno jako double:
float f = 10.1f; double d = 10.02;
Jako desetinný separátor používáme ve zdrojovém kódu vždy tečku, nehledě na to, jaké máme v operačním systému regionální nastavení (například v českém prostředí se tradičně používá desetinná čárka).
char
Podívejme se ještě blíže na typ char, který může
reprezentovat buď celé číslo nebo znak.
Pro reprezentaci znaku použijeme char takto:
{C_CONSOLE}
char z = 'A';
printf("%c", z);
{/C_CONSOLE}
A když chceme, aby char reprezentoval číslo:
{C_CONSOLE}
char i = 127;
printf("%d", i);
{/C_CONSOLE}
unsigned typy
Většinu datových typů můžeme ještě předsadit klíčovým slovem
unsigned, např. vytvoříme proměnnou typu
unsigned int a podobně, ale pozor, nefunguje to pro čísla
desetinná. Sign označuje znaménko čísla a unsigned znamená,
že číslo znaménko nemůže obsahovat. Výsledkem je, že je taková
proměnná vždy nezáporná a vejde se do ni proto i 2x větší číslo,
jelikož není využita záporná část. Uveďme si příklad u typu
char:
| Typ | Rozsah | 
|---|---|
| char | -128 až 127 | 
| unsigned char | 0 až 255 | 
Zkusme jsi nyní něco naprogramovat  Vytvoříme si "tabulku" s různými datovými typy a jejich
velikostmi. Založíme si nový projekt s názvem
 Vytvoříme si "tabulku" s různými datovými typy a jejich
velikostmi. Založíme si nový projekt s názvem Tabulka a jeho
kód upravíme takto:
#include <stdio.h> #include <stdlib.h> #include <limits.h> int main(int argc, char** argv) { return (EXIT_SUCCESS); }
Pro názornost jsem vymazal šedou dokumentaci, ale klidně si ji tam nechte.
Změna spočívá v includování limits.h, což nám umožňuje
přístup k funkcím pro zjištění nejvyšší hodnoty datových typů.
Pro zjištění velikosti datového typu použijeme funkci
sizeof(), která nám vrátí velikost datového typu v
bajtech.
Pro zjištění rozsahu použijeme konstanty (ty si vysvětlíme později) ze
souboru limits.h, který jsme si includovali.
Zmíněnou funkci tedy vyzkoušejme:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char** argv) {
int velikostIntu = sizeof(int); // Ukládáme si velikost intu.
printf("Int zabírá %d bajt/y/ů místa \n", velikostIntu); // Vypisujeme velikost intu
    return (EXIT_SUCCESS);
}
A toto by měl být výsledek:
Konzolová aplikace
Int zabírá 4 bajt/y/ů místa
Nyní jsme vyzkoušeli, že funkce sizeof() nám vrátí
velikost zadaného datového typu. Pojďme vyzkoušet ještě konstanty ze
souboru limits.h, které by nám měly vrátit největší možné
číslo zadaného datového typu:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char** argv) {
int maximalniRozsah = INT_MAX; // Ukládáme maximalní rozsah intu
printf("Maximální rozsah intu je %d \n", maximalniRozsah); // Vypisujeme maximální rozsah intu
    return (EXIT_SUCCESS);
}
A toto by měl být výsledek (pokud nemáte jiný typ procesoru, viz. výše):
Konzolová aplikace
Maximální rozsah intu je 2147483647
Když teď víme, že nám konstanty i funkce fungují, můžeme se vrhnout
do programování konzolové tabulky  Kód bude vypadat asi tak to:
 Kód bude vypadat asi tak to:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char** argv) {
int maxInt = INT_MAX;
short maxShort = SHRT_MAX;
char maxChar = CHAR_MAX;
char sizeInt = sizeof(int);
char sizeShort = sizeof(short);
char sizeChar = sizeof(char);
printf("INT: zabírá %d bajt/y/ů a největší možné číslo je %d\n", sizeInt, maxInt);
printf("SHORT: zabírá %d bajt/y/ů a největší možné číslo je %d\n", sizeShort, maxShort);
printf("CHAR: zabírá %d bajt/y/ů a největší možné číslo je %d\n", sizeChar, maxChar);
    return (EXIT_SUCCESS);
}
Takto by měl vypadat výsledek:
Konzolová aplikace
INT: zabírá 4 bajt/y/ů a největší možné číslo je 2147483647
SHORT: zabírá 2 bajt/y/ů a největší možné číslo je 32767
CHAR: zabírá 1 bajt/y/ů a největší možné číslo je 127
To bychom měli.
V příští lekci, Podmínky (větvení) v jazyce C, nás čekají podmínky 
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
            
                Staženo 311x (31.75 kB)
                                    
                     Aplikace je včetně zdrojových kódů                                            v jazyce C                                                                        
        
 
				
