2.1 Identifikatory,
klicova slova a komentare.
2.2 Zakladni typy dat
2.3 Konstanty a 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.
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:
prvnim symbolem smi byt pismeno nebo
podtrzitko
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.
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.
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.
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 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:
0
(cislice nula) uvadi konstanty v
osmickove soustave 0x
nebo 0X
(cislice nula
nasledovana znakem x) uvadi konstanty v
sestnactkove soustave 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 long
13
. Oba sufixy je mozno spojit, takze
napriklad:
123UL
je (desitkova) konstanta 123 typu unsigned long
.
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 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 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.
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
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:
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
Nazev: | Programovani v jazyce C |
Autor: | Petr Saloun |
Do HTML prevedl: | Kristian Wiglasz |
Posledni uprava: | 29.11.1996 |