3. cvičení
Přehled základních datových typů
Paměť počítače je lineární a rozdělená na bajty (1 bajt = 8 bitů). Každý bajt v paměti má svou jedinečnou adresu. Interpretace jednotlivých dat uložených v paměti počítače závisí na datovém typu příslušné proměnné.
Typ | Velikost (bits) | Minimální hodnota | Maximální hodnota | Poznámky |
---|---|---|---|---|
bool |
8 | 0 | 1 | Pro použití typu bool je třeba #include <stdbool.h> . |
char |
8 | -128 | 127 | 7-bitové kódování znaků pomocí ASCII tabulky. |
unsigned char |
8 | 0 | 255 | |
short |
16 | -32768 | 32767 | Typ pro reprezentaci celých čísel. |
unsigned short |
16 | 0 | 65535 | Typ pro reprezentaci nezáporných celých čísel. |
int |
32 | -2147483648 | 2147483647 | Typ pro reprezentaci celých čísel. |
unsigned int |
32 | 0 | 4294967295 | Typ pro reprezentaci nezáporných celých čísel. |
long |
64 | -9223372036854775808 | 9223372036854775807 | Typ pro reprezentaci celých čísel. |
unsigned long |
64 | 0 | 18446744073709551615 | Typ pro reprezentaci nezáporných celých čísel. |
float |
32 | \(\approx 1.175 \times 10^{-38}\) | \(\approx 3.402 \times 10^{38}\) | Typ pro reprezentaci racionálních čísel. |
double |
64 | \(\approx 2.225 \times 10^{-308}\) | \(\approx 1.797 \times 10^{308}\) | Typ pro reprezentaci racionálních čísel. |
Při vyhodnocování aritmetických operací obsahujících proměnné různých typů
dochází k implicitní konverzi proměnných na „ten větší“ ze zúčastněných typů.
Tedy např. součet proměnné typu short
a proměnné typu int
proběhne tak,
že se hodnota proměnné typu short
převede na typ int
a součet se provede
pro typ int
. Při výpočtech může dojít k chybám způsobeným přetečením nebo
podtečením maximálního rozsahu hodnot pro daný typ.
Pozor: Celočíselné proměnné lze dělit pouze celočíselně. Pokud je potřeba
neceločíselný výsledek, je třeba explicitně provést přetypování, např.
(float) x / y
.
Pozor: Konverze na typ bool
funguje jinak než konverze na ostatní
celočíselné typy. Výraz (bool) 0.5
dává 1, kdežto (int) 0.5
dává 0.
Pozor: Hodnoty typu char
(znaky) je třeba ve zdrojovém kódu zapisovat
pomocí jednoduchých uvozovek, tedy 'a'
, 'b'
, 'c'
apod. Pomocí dvojitých
uvozovek se zapisují textové řetězce, kterými se budeme zabývat později.
Důležité pojmy
- Rekurzivní funkce je funkce volající sama sebe. Aby se program nezacyklil, je nutné předávat jiné hodnoty parametrů funkce a správně ošetřit počáteční (resp. koncovou) podmínku.
Probrané příklady
-
Program demonstrující deklaraci proměnných celočíselného typu
int
a neceločíselného typufloat
, provedení operace sčítání a výpis výsledku pomocí funkceprintf
.#include <stdio.h> int main() { float a = 1.5; int b = 2; float c = a + b; printf("%f + %d = %f\n", a, b, c); return 0; }
Proměnné jsou vypisovány pomocí speciálního symbolu pro daný datový typ (
%d
pro typint
a%f
pro typfloat
). Přehled všech možností funkceprintf
bude ukázán později. -
Program pro výpočet obvodu a obsahu kruhu.
-
Výpočet faktoriálu pomocí rekurzivní funkce. Pro příliš vysoké hodnoty proměnné
n
dojde při výpočtu k tzv. přetečení rozsahu pro daný typ (zdelong
) a program vrátí špatný výsledek.#include <stdio.h> long factorial(int n) { if (n == 1) return 1; else return n * factorial(n - 1); } int main() { int n = 10; long f = factorial(n); printf("%d! = %ld\n", n, f); return 0; }
Nerekurzivní funkci pro výpočet faktoriálu lze zapsat např. pomocí cyklu
for
:long factorial(int n) { long vysledek = 1; for (int i = 2; i <= n; i++) vysledek *= i; return vysledek; }
Nebo pomocí cyklu
while
:long factorial(int n) { long vysledek = 1; while (n > 1) { vysledek *= n; n--; } return vysledek; }
-
Výpočet členů Fibonacciho posloupnosti. Rekurzivní verze je jednoduchá, ale velmi pomalá (i výpočet prvních 200 členů trvá dlouho):
#include <stdio.h> int fibonacci(int n) { if (n == 1) return 1; else if (n == 2) return 1; else return fibonacci(n - 1) + fibonacci(n - 2); } int main() { for (int i = 1; i <= 200; i++) printf("fibonacci(%d) = %d\n", i, fibonacci(i)); return 0; }
Nerekurzivní verze je komplikovanější, ale mnohem rychlejší. Efektivitu výpočtu zdůvodňovat nebudeme, to bude náplní předmětu ZALG v letním semestru.
int fibonacci(int n) { // dve pomocne promenne pro predchozi cleny posloupnosti int f_i_minus_1 = 1; int f_i_minus_2 = 1; for (int i = 3; i <= n; i++) { // vypocet aktualniho clenu int f_i = f_i_minus_1 + f_i_minus_2; // posun promennych pro dalsi iteraci f_i_minus_2 = f_i_minus_1; f_i_minus_1 = f_i; } // vysledek (clen f_n) je v promenne f_i_minus_1 return f_i_minus_1; }