Predchozi kapitola

Obsah

Konec

Nasledujici kapitola

2. Konstanty, promenne a deklarace.

2.1 Identifikatory, klicova slova a komentare.
2.2
Zakladni typy dat
2.3
Konstanty a promenne.

Konstanty
Celociselne konstanty
Racionalni konstanty
Znakove konstanty
Konstantni retezce
Promenne

2.4. Ukazatele.


V teto kapitole se seznamime s klicovymi slovy, identifikatory, komentari. Pozname rozdil mezi konstantou a promennou a naucime se nejen zakladni datove typy, ale i tvorbu novych typu dat.

2.1. Identifikatory, klicova slova a komentare.zpet

Klicova slova maji specialni vyznam pro prekladac C. Zadny identifikator nemuze mit ve fazi prekladu stejne zneni jako klicove slovo. ANSI norma urcuje nasledujici klicova slova:

auto double int struct
break else long switch
case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while

Identifikatory jsou jmena, ktera davame napriklad promennym, funkcim a typum. Identifikator se musi lisit od kterehokoliv klicoveho slova. Nejvyssi pocet znaku identifikatoru je implementacne zavisly. ANSI rika, ze interni identifikator muze byt dlouhy 31 znaku, externi 6.

Identifikator je tvoren posloupnosti alfanumerickych znaku a podtrzitka, pricemz musi byt splneny nasledujici podminky:

Jazyk C v identifikatorech rozlisuje mala a velka pismena1. Nasledujici identifikatory jsou tedy navzajem odlisne:

identifikator Identifikator IDENTIFIKATOR IdEnTiFiKaToR

Komentar je cast programu umistena mezi dvojici parovych symbolu /* a */. Komentar muze vypadat napriklad takto:

/* Toto je komentar,
 a toto je jeho pokracovani na druhem radku. */
...
/*
  if (uk->chyba)
    {
     ts->pom_info++;
    }
  else
 nepripustim chybu, ladim stejne nasucho
*/
...

Komentare obvykle umistujeme do zdrojoveho textu z duvodu jeho lepsi citelnosti. Casto popisujeme nektere dulezite vlastnosti zdrojoveho textu prave v komentari. Komentarem si muzeme rovnez prechodne vypomahat ve fazi tvorby a ladeni programu:

Bily znak je jeden z nasledujicich symbolu: mezera, tabelator, novy radek, posun radku, navrat voziku, nova stranka a vertikalni tabelator2. Bile znaky spolu s operatory a oddelovaci stoji mezi identifikatory, klicovymi slovy, retezci a konstantami3pouzitymi ve zdrojovem textu. Prekladac povazuje rovnez komentar za bily znak.

2.2. Zakladni typy datzpet

Zakladni typy dat delime na celociselne, racionalni4, spolecne je nazyvame aritmeticke datove typy, znaky a na ukazatele. Celociselne datove typy mohou obsahovat modifikatory unsigned respektive signed, cimz muzeme pozadovat hodnoty prislusneho typu bez znamenka, resp. se znamenkem5. V cecku mame tedy k dispozici vsechny potrebne zakladni typy i s jejich pripadnymi modifikacemi. Jejich prehled spolu s pametovymi naroky a jejich ceskym vyznamem nasleduje:

datovy typ pocet bitu vyznam
char, unsigned char, signed char 8 znak
short, unsigned short, signed short 16 kratke cele cislo
int, unsigned int, signed int 16 nebo 32 cele cislo
long, unsigned long, signed long 32 dlouhe cele cislo6
enum 8|16|32 vyctovy typ
float 32 racionalni cislo
double 64 racionalni cislo s dvojitou presnosti
long double 80
pointer 16|32 ukazatel

Pokud nas prekvapi vice moznych hodnot ve sloupci pocet bitu, pak vezme, ze tuto hodnotu urcuje jak prekladac, a pripadne u nekterych OS i pametovy model, tak skutecnost zasadnejsiho vyznamu. Totiz jedna-li se o prekladac generujici cilovy kod sestnactibitovy ci tricetidvoubitovy (ovlivni typ int).

Nebudete-li si jisti rozsahem hodnot jednotlivych aritmetickych typu, podivejte se do souboru LIMITS.H (pro celociselne typy), respektive FLOAT.H (pro typy racionalni). V nich najdete nejmensi pripadne i nejvetsi mozne hodnoty, ktere prislusny prekladac pripousti.

Pri nasich prvnich krocich vychazejme z nasledujicich zasad, ktere jsou soucasti ANSI C. Jak celociselne, tak racionalni typy je mozno co do poctu obsazenych bitu7 (a z toho vyplyvajiciho rozsahu moznych hodnot) usporadat takto:

short <= int <= long
float <= double <= double float
a dale plati, ze char vyzaduje 8 bitu.

Na tomto miste venujme nekolik slov konverzim aritmetickych typu. Vyraz slozeny z operandu ruzneho aritmetickeho typu bude vyhodnocen a prislusne typove konverze probehnou automaticky. Tim ovsem neni receno, ze vysledek bude takovy, jaky ocekavame na zaklade znalosti nasi skolni matematiky. Konverzim aritmetickych typu se podrobneji budeme venovat pozdeji.

2.3. Konstanty a promenne.zpet

Vetsina objektu (entit), oznacenych identifikatorem musi byt deklarovana drive, nez je pouzita. Konstanty, typy, promenne a funkce k takovym objektum patri.

S konstantami a promennymi jsou uzce spojeny dva pojmy, deklarace a definice8. Deklaraci urcujeme typ objektu. Informace o typu je prekladacem pouzivana pri typove kontrole, typovych konverzich, atd. V miste definice definujeme hodnotu promenne ci posloupnost prikazu funkce. Z uvedeneho vyplyva duvod, proc muzeme napriklad funkci vicekrat deklarovat, ale pouze jedenkrat definovat.

Konstanty a promenne mohou nabyvat hodnot jak zakladnich datovych typu, tak typu uzivatelsky definovanych. Prirozene mohou tvorit i struktury typu pole. V teto casti se poli konstantnich i promennych vektoru nebudeme zabyvat podrobneji, omezime se na jejich definice.

Konstantyzpet

Konstanty jsou symboly, reprezentujici nemennou ciselnou nebo jinou hodnotu. Prekladac jazyka jim priradi typ, ktery teto hodnote odpovida. Z konstant odpovidajicich si typu muzeme vytvaret konstantni vyrazy. Tyto vyrazy musi byt regularni (zjednodusene musi byt snadno vyhodnotitelne behem prekladu). Nesmi obsahovat zadny z nasledujicich operatoru (nejsou-li pouzity mezi operandy operatoru sizeof):

Konstantam s vhodne zvolenymi identifikatory davame prednost napriklad pred primym uvedenim konstantni hodnoty jako meze cyklu nebo dimenze pole9. Modifikace programu pak probiha velmi snadno zmenou hodnoty konstanty. Odpada obtizne uvazovani, zdali ta ci jina hodnota ma byti modifikovana ci nikoliv. Konstanty maji rovnez urcen typ. Tim je umoznena typova kontrola.

Konstanty definujeme po klicovem slove const nasledovanem typem konstanty, jejim identifikatorem a po rovnitku jeji hodnotou ukoncenou strednikem. Jedna-li se o vektor, nasleduje za identifikatorem dvojice hranatych zavorek, zpravidla obsahujici jeho dimenzi. Prvni prvek pole ma vzdy index0. Konstanty muzeme definovat treba takto:

const int konstanta = 123;
const celociselna = -987;

const float CPlanck = 6.6256e-34;
const char male_a = 'a';
const char *retezec = "Konstantni retezec."
const float meze[2] = {-20, 60};
const char rimska_znaky[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
const int rimska_hodn[] = {1, 5, 10, 50, 100, 500, 1000};

Neuvedeme-li typ, jako v pripade druhe konstanty, je implicitne chapan typ int. Muzeme definovat konstanty vsech zakladnich datovych typu. Promenna meze predstavuje dvouprvkove pole konstant typu float. Prvky pole nabyvaji se vzrustajicim indexem hodnoty v poradi, jak jsou v definici zapsany. Posledni dve konstanty jsou pole konstantnich hodnot. Uvedeme-li vsechny pozadovane hodnoty na prave strane definice, nemusime v hranatych zavorkach uvadet dimenzi pole10.

Celociselne konstantyzpet

Celociselne konstanty jsou tvoreny zapisem celeho cisla. Mohou byt zapsany v desitkove, osmickove pripadne v sestnactkove ciselne soustave. Nejprve tedy jednoduche zapisy:

123 -987 255 4567 -4567

ktere predstavuji celociselne konstanty. V poradi druha a posledni predstavuji zaporne hodnoty, ostatni jsou kladne.

Nyni si uvedeme pravidla, podle nichz urcujeme zaklad ciselne soustavy konstanty:

Nasleduje nekolik desitkovych konstant zapsanych ve trech moznych ciselnych soustavach11:

desitkovy osmickovy sestnactkovy12
123 0173 0x7b
-987 0176045 0xfc25
255 0377 0xff
4567 010727 0x11d7
-4567 0167051 0xee29

Jestlize prefix zapisu celociselne konstanty urcoval zaklad ciselne soustavy, pak sufix, pokud je uveden, urcuje celociselny datovy typ. A to nasledovne: u nebo U modifikuje typ na unsigned, zatimco l nebo L rika, ze jde o typ long13. Oba sufixy je mozno spojit, takze napriklad:

123UL

je (desitkova) konstanta 123 typu unsigned long.

Racionalni konstantyzpet

Racionalni konstanty umoznuji zapsat ciselnou konstantu, ktera nemusi byt celociselna. Vnitrne je reprezentovana ve tvaru, ktery obsahuje mantisu a exponent, oboji s pripadnym znamenkem.

Implicitni typ racionalni konstanty je double. Napriklad 12.34e5. Chceme-li, aby konstanta byla typu longdouble, pripojime k zapisu pismeno L, tedy napriklad

12.34e5L.

Pro lepsi predstavu dava nasledujici tabulka prehled nekterych vlastnosti racionalnich datovych typu:

typ bitu mantisa exponent rozsah absolutnich hodnot (priblizne)
float 32 24 8 3.4 10-38 az 3.4 10+38
double 64 53 11 1.7 10-308 az 1.7 10+308
long double 80 64 15 3.4 10-4932 az 1.1 10+4932

Presne definuje racionalni datove typy norma IEEE 754.

Znakove konstantyzpet

Znakove konstanty jsou tvoreny pozadovanym znakem, respektive posloupnosti znaku, uzavrenym mezi apostrofy. Na nasledujicim radku je zapsano nekolik znakovych konstant:

'a' 'A' 'S' 'n' '}' '#' '"'

Prvni dve nas jiste neprekvapi, dalsi dve nemusi byt nutne k dispozici na vsech systemech (byt podpora narodniho prostredi je cim dal vetsi samozrejmosti). Dalsi dva znaky zase nejsou k dispozici na standardnich ceskych klavesnicich, ale cecko si bez nich predstavit nedovedeme. No a posledni znakova konstanta jsou uvozovky. Jimi si pripravujeme nasledujici otazku.

Jak zapiseme znakovou konstantu apostrof? A co pripadne jine specialni znaky (ridici symboly, znaky nenachazejici se na klavesnici, ...). Zde si pomahame symbolem opacne lomitko a nejmene jednim dalsim znakem. Temto posloupnostem rikame escape sequence. Ty mohou byt jednoduche, kdy opacne lomitko nasleduje jediny znak. Nebo nasleduje osmickovy ci (po x) sestnactkovy kod znaku. Tak jsme schopni zadat i znak, ktery se na klavesnici nenachazi, ale jehoz kod je nam znam. Prehled escape sequenci obsahuje tabulka:

posloupnost jmeno Ctrl-znak vyznam
\a Alert (Bell) G pipnuti
\b Backspace H navrat o jeden znak
\f Formfeed L nova stranka nebo obrazovka
\n Newline J presun na zacatek noveho radku
\r Carriage return M presun na zacatek aktualniho radku
\t Horizontal tab I presun na nasledujici tabelacni pozici
\v Vertical tab K stanoveny presun dolu
\\ Backslash obracene lomitko
\' Single quote apostrof
\" Double quote uvozovky
\? Question mark otaznik
\OOO ASCII znak zadany jako osmickova hodnota
\xHHH ASCII znak zadany jako sestnactkova hodnota

Konstantni retezcezpet

Konstantni retezce - literaly jsou na rozdil od znakovych konstant tvoreny vice nez jednim znakem, zpravidla slovem ci vetou (tedy znakovou posloupnosti, retezcem). Zacatek a konec retezce jsou vymezeny uvozovkami. Nasledujici retezce jsou umyslne psany cesky:

"dve slova" "Cela tato veta tvori jeden retezec." "a" "Ahoj!"

Na predposledni retezec musime upozornit. Jedna se o retezcovou konstantu tvorenou pismenem a, tedy retezcem delky jeden znak. Nesmime ji zamenovat se znakovou konstantou. Ta je vymezena dvema apostrofy. Navic, znakova konstanta, bez ohledu na jeji zapis, predstavuje jeden jediny znak, zatimco retezcova konstanta muze mit i znacnou delku.

Pokud konstantni retezec obsahuje specialni symboly, zapisujeme je obdobne, jako jsme to cinili u znakovych konstant. Napriklad:

"\tPo uvodnim tabelatoru prejdeme na novy radek\na pipneme\a."

Pouzili jsme jednoduche escape sequence. Pokud bychom po nich udelali mezeru, byla by tato rovnez obsazena i ve vyslednem retezci. A to nechceme. A jeste jedna ukazka delsi retezcove konstanty:

"Tato delsi retezcova konstanta obsahuje opacne lomitko \\, \
a pokracuje na dalsim radku od jeho zacatku. " "Navic je takto \
rozdelena."

"Jednodussi pokracovani na dalsim radku "

"vypada takto, pak nemusime zacinat hned na zacatku."

Prvni dva radky jsou ukonceny opacnym lomitkem. Tim je receno, ze retezec pokracuje na nasledujicim radku. Jednodussi je ovsem konstrukce, pri niz ukoncit retezec uvozovkami, ukoncime radek a pokracuneme novym retezcem kedkoliv na novem radku. Prekladac totiz dva retezce, oddelene pouze bilymi znaky, spoji v retezec jeden.

Promennezpet

Promenne jsou pametova mista pristupna prostrednictvim identifikatoru. Hodnotu promennych muzeme behem vypoctu menit. Tim se promenne zasadne odlisuji od konstant, ktere maji po celou dobu chodu programu hodnotu nemennou - konstantni.

Promenne deklarujeme uvedenim datoveho typu, jez je nasledovan identifikatorem, nebo seznamem identifikatoru, navzajem oddelenych carkami. Deklarace konci strednikem. Soucasne s deklaraci promenne muzeme, ale nemusime, definovat i jeji pocatecni hodnotu:

int a, b, c, pocet = 0;
float x, prumer = 0.0, odchylka = 0.0;
float y;

ANSI C povazuje konstanty za promenne s nemennou hodnotou. V zavislosti na pouzitem prekladaci muze byt tato hodnota umistena ve vyrazu primo. Pak ji nemusi byt vyhrazeno pametove misto tak, jak by bylo vyhrazeno pro promennou.14

2.4. Ukazatele.zpet

Ukazatel predstavuje adresu pametoveho mista. Jeho hodnota rika, kde je ulozen nejaky objekt. Soucasti deklarace ukazatele je i informace o typu dat, ktere jsou na ziskane adrese ocekavany.

int *integer_ptr; /* integer_ptr je ukazatel na integer */

Hodnota integer_ptr predstavuje adresu pameti a *integer_ptr je celociselna hodnota ulozena na teto adrese. Casto pouzivame pojem dereference ukazatele. Nasledujici hypoteticky priklad pracuje s adresou 1004, kam zapise hodnotu 123:

int *p; p = 1004; *p = 123;

Pamet by po techto prikazech vypadala nasledovne (zmenena hodnota je zvyraznena, ostatni pametova mista maji nahodny obsah):

Hodnoty 15 0 123 65
Adresy 1002 1003 1004 1005

Obvyklou chybou zacatecniku je pouziti ukazatele bez jeho predchozi inicializace (alokace pametoveho mista). Neinicializovany ukazatel muze ukazovat na kriticke oblast pameti a jeho pouziti muze vest (v operacnich systemech jako je MS-DOS) i k havarii systemu. Takto tedy ne:

Ukazatele

Zatim vystacime bez alokace pameti. Potrebujeme ovsem prostredek ke ziskani adresy existujici promenne. Pak se budeme korektne odkazovat na vyhrazene pametove misto.

int i, *pi;
pi = &i;
*pi = 123;

Po definici promenne i typu int, a ukazatele pi na typ int v prvnim radku nasleduje ziskani adresy promenne i. Na tuto adresu se odkazuje ukazatel pi. Jeho dereferenci na leve strane prikazu prirazeni, ulozime prislusnou hodnotu na pametove misto, na ktere ukazuje.

Ukazatele, o kterych jsme dosud pojednavali, byly spojene s nejakym konkretnim typem. Tato skutecnost je prinosem, nebot umoznuje typovou kontrolu. Jsou vsak okamziky, kdy proste potrebujeme ukazovat ukazatelem do pameti a nemame na mysli konkretni datovy typ. ANSI norma pro takovou situaci zavadi prazdny fiktivni typ void.


Vysvetlivky:

1 Tato skutecnost cini obtize zejmena zacatecnikum prechazejicim k cecku z vetsiny jinych jazyku.
2 V obvyklem zdrojovem textu se nejcasteji muzeme setkat s prvnimi tremi predstaviteli bilych znaku.
3 Vsechny uvedene pojmy se spolecne oznacuji jako tokeny. Pro prekladac predstavuji dale nedelitelne
4 Tento termin nejlepe vystihuje omezenou delku mantisy, kterou mohou cisla s desetinnou teckou
5 Tato varianta je casto pouzivana u typu char, kde muze byt rovnez zdurazneno jak signed char,
6 Celociselny typ long rovnez muzeme psat jako long int. Obdobne short predstavuje totez, co
7 Pozdeji se dozvime, ze ke zjisteni potrebne pameti pro hodnotu prislusneho typu je mozno pouzit
8 Tyto pojmy budeme pozdeji diskutovat i v souvislosti s funkcemi.
9 Konstantam uvedenym primo ve zdrojovem textu se rika magicka cisla. Vhodny identifikator leccos
10 Pro hloubavejsi ctenare muzeme uvest i moznost, jak pozdeji zjistit, kolik prvku takove pole ma.
11 Nutno podotknout, ze se jedna o sestnactibitovy kod, tedy i typ int je sestnactibitovy.
12 Osmickove a sestnactkove konstanty jsou chapany bez znamenka. Sestnactkove cifry muzeme
13 Casto se jako sufix pouziva velke L, nebot male l je snadno zamenitelne s cislici jedna.
14 Tato skutecnost zavisi rovnez na pouziti konstanty. Odvolavame-li se na jeji adresu, je ji pametovy


Predchozi kapitola

Obsah

Zacatek

Nasledujici kapitola


Nazev: Programovani v jazyce C
Autor: Petr Saloun
Do HTML prevedl: Kristian Wiglasz
Posledni uprava: 29.11.1996