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
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:
#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 310x (31.75 kB)
Aplikace je včetně zdrojových kódů v jazyce C