Kapitola 3. Základní typy, konstanty a proměnné

Obsah

3.1. Identifikátory
3.2. Klíčová slova
3.3. Komentáře
3.4. Odsazovače
3.5. Čísla
3.6. Pojmenovávání objektů
3.7. Konstanty
3.8. Celočíselné konstanty
3.9. Racionální konstanty
3.10. Znakové konstanty
3.11. Řetězce
3.12. Proměnné
3.13. Ukazatele
3.14. Opakování

Časová náročnost
Časová náročnost kapitoly: 1 hodina 15 minut

V této části se seznámíme s identifikátory, klíčovými slovy, komentáři. Řekneme si něco o číslech, konstantách - a to celočíselných, racionálních a znakových a nezapomeneme ani na řetězce, proměnné a ukazatele.

Potřebné znalosti
Potřebné znalosti

K zvládnutí obsahu této kapitoly je nutné mít znalosti z kapitoly 2 - tedy znát základní strukturu programu v jazyce C a alespoň intuitivně chápat vstup a výstup programů v jazyce C.

3.1. Identifikátory

Časová náročnost
Časová náročnost: 2 minuty

Identifikátory jsou jména, která dáváme například proměnným, funkcím a typům. Délka identifikátoru je v normě ISO C omezená 31 znaky.

upozornění

Pro vytváření identifikátorů platí:

  • Prvním symbolem smí být pouze písmeno nebo podtržítko
  • Poté následuje libovolná kombinace písmen, číslic a podtržítek
  • POZOR! Rozlišují se malá a velká písmena!
Jednoduchý příklad
Příklad:

identifikátor a Identifikátor

jsou dva různé identifikátory

3.2. Klíčová slova

Časová náročnost
Časová náročnost: 5 minut

Klíčová slova jsou zvláštní identifikátory, které mají speciální význam pro jazyk C. Proto je nesmíme používat v jiném významu, než jak určuje norma ISO C, což znamená, že nesmí být použita jako jména proměnných nebo funkcí.

Použití malých písmen v klíčových slovech je také důležité. Například RETURN nebude považováno za klíčové slovo return.

V jazyce C jsou definovány následující klíčová slova:

Důležité

Tabulka 3.1.

autodoubleintstruct
breakelselongswitch
caseenumregistertypedef
charexternreturnuninon
constfloatshortunsigned
continueforsignedvoid
defaultgotosizeofvolatile
doifstaticwhile

3.3. Komentáře

Časová náročnost
Časová náročnost: 5 minut

Komentář je poznámka, kterou přidáváme do zdrojového kódu programu. Všechny komentáře jsou překladačem ignorovány. Komentáře se používají hlavně pro popis významu a účelu zdrojového kódu. Je to část programu umístěná mezi dvojici párových symbolů /* */. V tomto případě jde o komentář, který může zasahovat přes více řádků.

Jednoduchý příklad
Příklad:
printf("Ahoj");  /* toto je jednořádkový komentář */

/*
Toto je 
viceradkovy
komentar
*/

V jazyku C může být komentář umístěn kdekoliv, jen ne uprostřed klíčového slova, jména funkce nebo jména proměnné.

Komentář lze také použít pro dočasné vynechání řádků zdrojového textu. Stačí uzavřít vynechávanou část symboly pro začátek a konec komentáře.

Poznámka - Java
Pozn:
Jazyk Java zavádí dokumentační komentář, který je podkladem pro generovaní dokumentace.
Poznámka - C++
Pozn:
Jazyk C++ zavádí jednořádkový komentář uvozený dvojicí lomítek \\ - více viz Komentáře v jazyce C++.

3.4. Odsazovače

Časová náročnost
Časová náročnost: 3 minuty

Odsazovače, jinak také bílé znaky, jsou následující symboly:

Důležité

Tabulka 3.2.

mezera tabulátor
nový řádekposun řádku
návrat vozíkuvertikální tabulátor
nová stránka  

V obvyklém zdrojovém textu se nejčastěji můžeme setkat s prvními třemi představiteli odsazovačů. Odsazovače spolu s operátory a oddělovači stojí mezi identifikátory, klíčovými slovy, řetězci a konstantami použitými ve zdrojovém textu. Všechny uvedené pojmy se společně označují jako lexikální symboly. Pro překladač představují dále nedělitelné celky. Překladač považuje rovněž komentář za odsazovač.

3.5. Čísla

Časová náročnost
Časová náročnost: 8 minut

Čísla jsou v počítači uloženy ve formě nul a jedniček - tedy základní soustavou není soustava desítková, ale dvojková. Čísla jsou proto v paměti počítače uložena takovým způsobem, že jen celá čísla jsou uložena přesně - ovšem jen ve stanoveném rozsahu hodnot - zatímco u čísel reálných je k dispozici nejvýše jistý počet platných číslic plus exponent. Z výše uvedených skutečností musí vycházet každý programovací jazyk. V jazyce C dělíme základní typy dat na:

  • celočíselné
  • racionální
  • znaky
  • ukazatele

Úvodní dva typy společně nazýváme aritmetické datové typy.

Racionální typy
Pozn:
Racionálním typům se často říká dle jejich základního představitele float, správně se však jmenují čísla v pohyblivé řádové čárce.

Celočíselné datové typy mohou být takzvaně bezznaménkové, což znamená, že použijeme modifikátor unsigned. Tatáž vlastnost u znaků, například unsigned char, může být zajímavá kvůli kódování neanglických abeced v různých operačních systémech.

Základní typy dat:

Důležité

Tabulka 3.3.

Datový typ Počet bitůVýznam
char8znak
short16 krátké celé číslo
int32celé číslo
long32 dlouhé celé číslo
enum32výčtový typ
float32racionální číslo
double64racionální číslo s dvojitou přesností
long double80 ještě delší racionální číslo
pointer32 ukazatel

Dále platí:

Důležité
short <= int <= long 

float <= double <= long double 

char vyžaduje 8 bitů

Nebudete-li si jisti rozsahem hodnot jednotlivých aritmetických typů, podívejte se ve vašem systému do souboru limits.h - pro celočíselné typy, respektive do souboru float.h - pro typy racionální. V nich najdete nejmenší případně i největší možné hodnoty, které příslušný překladač připouští.

3.6. Pojmenovávání objektů

Časová náročnost
Časová náročnost: 2 minuty

S konstantami a proměnnými jsou úzce spjaty dva pojmy - deklarace a definice.

Deklarací určujeme typ objektu. Informace o typu je překladačem používána při typové kontrole, typových konverzích apod.

V místě definice definujeme hodnotu proměnné či posloupnost příkazů funkce.

3.7. Konstanty

Časová náročnost
Časová náročnost: 5 minut

Konstanty jsou pevně dané hodnoty, které nesmí být programem změněny.

Konstanty definujeme po klíčovém slově const následovaném typem konstanty, jejím identifikátorem a po rovnítku její hodnotou ukončenou středníkem. Jedná-li se o vektor (jednorozměrné pole), následuje za identifikátorem dvojice hranatých závorek, zpravidla obsahující jeho dimenzi. První prvek pole má vždy index 0. Nejlépe si možné definice konstant vysvětlíme na příkladech.

Jednoduchý příklad
Příklad:
const int konstanta = 15;
const konstanta = 21; // neuvedeme-li typ je implicitně přiřazen typ int
const char pismeno = 'r';
const char *retezec = "Jazyk C";
const float pole[3] = {-1, 0, 1};

/*
pokud uvedeme všechny hodnoty pole na jeho pravé straně 
nemusíme uvádět dimenzi
*/
const char pole[] = {'a', 'b'} 

Překladač jazyka C přidělí konstantám typ, který odpovídá přiřazované hodnotě. Z konstant odpovídajících si typů můžeme vytvářet konstantní výrazy. Tyto výrazy musí být vyhodnotitelné během překladu. Nesmí obsahovat žádný z následujících operátorů (nejsou-li použity mezi operandy operátoru sizeof):

Důležité
  • přiřazení
  • inkrementace a dekrementace
  • funkční volání
  • čárka

3.8. Celočíselné konstanty

Časová náročnost
Časová náročnost: 3 minuty

Důležité

Celočíselné konstanty jsou specifikovány jako čísla bez desetinné části. Jazyk C umožňuje použít tři typy celočíselných konstant:

  • desítkové - posloupnost číslic z nichž první nesmí být nula
  • osmičkové (oktalové) - číslice nula následována posloupností osmičkových číslic 0-7
  • šestnáctkové (hexadecimální) - číslice nula následována znakem x (nebo X) a posloupností hexadecimálních číslic 0-9, a-f, A-F

Jednoduchý příklad
Příklad:
desítkové - 15, 7, -25
oktalové - 065, 01, 036
hexadecimální - 0x12, 0x3A, 0XCD

Typ konstanty je určen implicitně, její velikostí, nebo explicitně používáním přípony L (nebo l - pozor snadno zaměnitelné s číslicí jedna) jako long, například 1234L. Druhá přípona, která explicitně určuje typ celočíselné konstanty je U (nebo u), jako unsigned, například 129U. Samozřejmě, že můžeme naspat i 21UL. Pak jde o unsigned long číslo.

3.9. Racionální konstanty

Časová náročnost
Časová náročnost: 6 minut

Důležité

Racionální datový typ ukládá čísla do paměti ve tvaru mantisa a exponent, obojí s případným znaménkem. Není-li uvedeno jinak, je typ racionální konstanty double. U konstant s pohyblivou řádovou čárkou je třeba použít desetinnou tečku následovanou desetinnou částí čísla. Jazyk C umožňuje zapisovat čísla s pohyblivou řádovou čárkou v semilogaritmickém tvaru.

Je však nutné dodržet následující formát:

mantisa E znaménko exponent
Jednoduchý příklad
Příklad:
123.45E1

Na výše uvedeném příkladu jsme pomocí semilogaritmické notace zapsali číslo 1234,5. Znaménko je nepovinné.

Norma ISO C říká, že rozsah exponentů pro všechny racionální datové typy je 10-38 až 10+38 a že přesnost typu float je nejméně šest platných číslic, přesnost typů double a long double je pak nejméně deset platných číslic.

Přesněji viz tabulka:

Tabulka 3.4.

TypPočet bitůMantisa Exponent Rozsah absolutních hodnot
float32 248 3.4*10-38 - 3.4*10+38
double6453 111.7*10-308 - 1.7*10+308
long double80 64 153.4*10-4932 - 3.4*10+4932

Má-li naše číslo větší absolutní hodnotu, než je hodnota pro typ tohoto čísla uvedená v tabulce dochází k přetečení a nastává chyba. V opačném případě, tedy když je absolutní hodnota čísla pro daný typ menší než je hodnota uváděná v tabulce, dochází k podtečení a výsledkem výrazu je nula.

3.10. Znakové konstanty

Časová náročnost
Časová náročnost: 4 minuty

Důležité

Znakové konstanty jsou tvořeny požadovaným znakem uzavřeným mezi apostrofy.

Jednoduchý příklad
Příklad:
'a'  'A'  'Š'  'ň'  '}'  '"'

Někdy však musíme jako znakovou konstantu použít i speciální znaky (řídící symboly, znaky nenacházející se na klávesnici). Zde si pomáháme symbolem zpětného lomítka a nejméně jedním dalším znakem. Těmto posloupnostem říkáme escape sekvence. Escape sekvence mohou být jednoduché - kdy zpětné lomítko následuje jediný znak. Nebo následuje osmičkový či šestnáctkový kód znaku. Tak jsme schopni zadat i znak, který se na klávesnici nenachází, ale jehož číselný kód je nám znám.

Jednoduchý příklad
Příklad:

Tabulka 3.5.

PosloupnostJménoVýznam
\aAlertpípnutí
\bBackspacenávrat o jeden znak
\fFormfeedodstránkování
\n New linena začátek nového řádku
\r Carriage returnna začátek aktuálního řádku
\t Horizontal tabna další tabelační pozici
\\ Backslash zpětné lomítko
\000  znak zadaný osmičkově
\xHH  znak zadaný šestnáctkově

3.11. Řetězce

Časová náročnost
Časová náročnost: 2 minuty

Důležité

Řetězec je posloupnost (pole) jednoho či více znaků. Začátek a konec řetězce jsou vymezeny uvozovkami.

Jednoduchý příklad
Příklad:
"Jazyk C"
"několik znaků v řetězci"
"r" //řetězcová konstanta tvořená řetězcem délky jeden znak = r
"Jazyk C\n" //speciální symboly zapisujeme opět pomocí escape sekvencí	

3.12. Proměnné

Časová náročnost
Časová náročnost: 5 minut

Důležité

Proměnné jsou paměťová místa přístupná prostřednictvím identifikátoru. Hodnotu proměnných můžeme během výpočtu měnit. Tím se proměnné zásadně odlišují od konstant, které mají po celou dobu chodu programu hodnotu neměnnou - konstantní.

Proměnné mohou obsahovat písmena, číslice 0-9 a podtržítko. Jména však nesmí začínat číslicí.

Během provádění programu se veškeré informace nacházejí v paměti. Tamtéž jsou umístěny pomocné hodnoty, mezivýsledky i výsledky. Rozhodně by nebylo vůbec příjemné k takovým hodnotám přistupovat prostřednictvím jejich adresy. Proto je vhodné si odpovídající paměťová místa pojmenovat a pak se na ně odkazovat jménem. Nejprve tedy deklarujeme typy a identifikátory proměnných, čímž pro ně vyhrazujeme v paměti počítače místo a současně si překladač spojuje s identifikátorem proměnné informaci o jejím umístění v paměti (adrese).

Proměnné deklarujeme uvedením datového typu, za kterým následuje identifikátor, nebo seznam identifikátorů, navzájem oddělených čárkami. Deklarace končí středníkem. Současně s deklarací proměnné můžeme, ale nemusíme, definovat i její počáteční hodnotu:

Jednoduchý příklad
Příklad:
int a, b, c;
float pi=3.14;

3.13. Ukazatele

Časová náročnost
Časová náročnost: 20 minut

Ukazatel je proměnná, která obsahuje paměťovou adresu jiného objektu. Například obsahuje-li proměnná nazvaná p adresu jiné proměnné nazvané q, pak se p nazývá ukazatel na q. Je-li proměnná q uložena v paměti na adrese 100, pak by měla proměnná p hodnotu 100.

Pro deklaraci proměnné typu ukazatel použijeme tento obecný formát:

Důležité
 typ *jméno-proměnné;

Typ zde znamená základní typ ukazatele. Základní typ určuje typ objektu, na který může ukazatel ukazovat. Všimneme si hvězdičky před jménem proměnné. Ta říká překladači, že se vytváří ukazatelová proměnná.

Uveďme si jednoduchý příklad ukazatele na celé číslo:

Jednoduchý příklad
Příklad:
int *p;

Jazyk C má dva speciální ukazatelové operátory: * a &. Operátor & vrací adresu proměnné, před kterou stojí. Operátor * vrací hodnotu uloženou na adrese, před kterou stojí.

Ukazatelový operátor
Pozn:
Ukazatelový operátor * nemá nic společného s operátorem násobení, který používá stejný symbol.
pointer.swf
Flashová animace
Kliknutím na ikonu spustíte test.
src/pointer1.c
Příklad 3.1.
/******************************
*	pointer1.c
*	19.03.2002
******************************/

#include <stdio.h>

int main (void)
{
 int *p, q;
 q = 199;   /* priradi q hodnotu 199 */
 p = &q;   /* priradi p adresu q */
 printf("%d", *p);	/* zobrazi hodnotu q pomoci ukazatele */
 return 0;
}

Tento program vypíše na obrazovku hodnotu 199.

Projděme si však jednotlivé části programu.

První řádek

 int *p, q;

nadefinuje dvě proměnné. p - ukazatel na celé číslo a q - což je celé číslo.

Poté je q přiřazena hodnota 199

q = 199;

Následně přiřadíme p adresu q. Tento řádek můžeme přečíst jako: Přiřaď p adresu q.

p = &q;

Nakonec vytiskneme hodnotu ukazatele q. Operátor * můžeme vyjádřit jako: na adrese a celý řádek pak přečíst jako: vypiš hodnotu na adrese q.

printf("%d", *p);

Nyní přepišme tento program tak, že hodnotu do q přiřadíme nepřímo přes ukazatel p.

src/pointer2.c
Příklad 3.2.
/******************************
*	pointer2.c
*	19.03.2002
******************************/

#include <stdio.h>

int main (void)
{
 int *p, q;
 p = &q;   /* ziskani adresy q */
 *p = 199;	   /* priradi q hodnotu pomoci ukazatele */
 printf("hodnota q je %d", q);
 return 0;
}

Nyní si ukážeme jak jednoduše lze udělat chybu.

Jednoduchý příklad
Příklad:
int q;
double *p;

p = &q;
p = 100.2;

Ikdyž je tento úsek syntakticky v pořádku přesto není správný. Ukazateli p je přiřazena adresa čísla int. Tato adresa je pak použita na levé straně přiřazovacího příkazu pro přiřazení hodnoty s pohyblivou řádovou čárkou. Jelikož je však číslo typu int obvykle kratší než double, způsobí tento přiřazovací příkaz přepsání paměti sousedící s q. Proto jsou důležité základní typy ukazatelů.

Další možný chybný zápis vzniká tehdy, pokud se snažíme použít ukazatel dříve než je do něj přiřazena adresa proměnné. V takovém případě program pravděpodobně zhavaruje. Je důležité si uvědomit, že deklarace ukazatelové proměnné pouze vytvoří proměnnou schopnou pojmout adresu paměti. Nedá ji však žádnou smysluplnou hodnotu.

Jednoduchý příklad
Příklad:
int *p;

*p = 10;  //chyba - ukazatel p na nic neukazuje!

Místa, na která se ukazatel odkazuje (jejichž adresu obsahuje) se mohou lišit. Takže můžeme například psát cykly, v nichž pomocí jediného ukazatele postupně přistupujeme ke všem prvkům pole. Je nemyslitelné, psát takový kód "natvrdo". Další možnosti použití ukazatelů se otevírají při dynamickém přidělování paměti.

Důležité

Je zde i jedno nebezpečí. Spočívá vtom, že nelze v programu zadávat absolutní adresu a očekávat, že bude použitelná jako paměťové místo.

Jednoduchý příklad
Příklad:
int *p;
p = 1024;
*p = 102;  //takže takto rozhodně NE!!
Důležité

Na závěr poměrně rozsáhlé části o ukazatelích se pokusíme znázornit problematiku ukazatelů graficky.

Předpokládejme že máme tuto část kódu:

int *p, q;

Dále mějme zadáno že q je umístěno v paměti na adrese 102 a p na adrese 100.

Poté následující příkaz

p = &q;

způsobí, že ukazatel p bude obsahovat hodnotu 102.

a po provedení příkazu

*p = 500;

bude obsah paměti vypadat takto

3.14. Opakování

Cvičení
Cvičení

Úkol k textu

Zadání 1)

Co je chybné v těchto jménech proměnných?

  1. pocet-hodin
  2. $suma
  3. black+white
  4. 9krat

Řešení

Úkol k textu

Zadání 2)

Co je chybně na této části programu?
/* timto se nacte cislo
scanf ("%d", &num);
Řešení

Úkol k textu

Zadání 3)

Napište program, který vytiskne Mám rád jazyk C - pomocí tří konstantních řetězců.
Řešení

Úkol k textu

Zadání 4)

Napište program, který přečte a vytiskne hodnotu typu long int.

Řešení

Úkol k textu

Zadání 5)

Co je to ukazatel?
Řešení

Úkol k textu

Zadání 6)

Jaké jsou ukazatelové operátory a jaká je jejich funkce?
Řešení
test3.swf
Test
Kliknutím na ikonu spustíte test.