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
inta 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 (
%dpro typinta%fpro typfloat). Přehled všech možností funkceprintfbude 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é
ndojde 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; }