Operační systém UNIX a jazyk C

Jan Brodský
Luděk Skočovský

SNTL Nakladatelství technické literatury Praha 1989, ISBN 80-03-00049-1

5. Programovací jazyk C


5.2 Objekty

5.2.1 Lexikální elementy

Cílem lexikální analýzy je nalézt maximální posloupnost znaků, která by mohla tvořit lexikální element.

Jazyk C rozeznává šest tříd lexikálních elementů. Jsou to identifikátory, klíčová slova, konstanty, řetězce, operátory a interpunkční znaky.

Kromě toho ignoruje mezery, tabulátory, nové řádky a poznámky, tzv. odsazovače (angl. white space). Někdy je však alespoň jeden odsazovač vyžadován k oddělení jinak na sebe navazujících identifikátorů, klíčových slov a konstant.

Poznámka je uvozena dvojicí znaků /* a končící dvojicí znaků */. Poznámky se nevnořují.

Identifikátor je tvořen posloupností písmen a číslic, první znak musí být písmeno (mezi písmena se počítá i podtržení). Jazyk rozlišuje malá a velká písmena a neklade omezení na počet znaků identifikátoru. Některé kompilátory (a sestavující programy) však tato omezení mají; pak se zpravidla uvažuje prvních osm znaků.

Roli klíčových slov mají identifikátory:


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
Pro snažší rozlišení budou v textu zvýrazněna půltučnou sazbou.

5.2.2 Konstanty a řetězce

Každé konstantě je přisouzen její typ. Reprezentace konstanty závisí na použitém technickém vybavení a je na programátorovi, aby si ověřil, že dostupná reprezentace stačí.

Celočíselná konstanta je zapisována jako posloupnost číslic. Nezačíná-li nulou, je interpretována dekadicky. Je-li však první číslice nula, považuje se za oktalový zápis. Následuje-li navíc za nulou písmeno x nebo X, jsou další znaky brány jako hexadecimální zápis (se znaky 0,1,...,9 a dále af nebo AF v roli hexadecimálních číslic). Tak např.

255, 0377 a 0xFF
jsou povolené zápisy téže celočíselné konstanty. Dekadický zápis se používá pro konstanty typu int, oktalový nebo hexadecimální zápis pro konstanty typu unsigned. V obou případech se při překročení rozsahu považuje za long. Například pro 16bitový počítač jsou čísla
65537, 0777777 nebo 0XFF00FF
brána jako long.

Celočíselnou konstantou lze explicitně prohlásit za long připojením písmene l nebo L:

1l, 0377L nebo 0XFL.

Znakové konstanty se zapisují jako znak uzavřený v apostrofech

'a', 'b' nebo 'z'.

Hodnotou znakové konstanty je nezáporné celé číslo vyjadřující reprezentaci znaku v použitém kódu. Tak v kódu ASCII má '0' hodnotu 48, 'a' hodnotu 0141.

Často je třeba zapsat znakovou konstantu pro řídící nebo nezobrazitelný znak. Pak se využívá konevence víceznakových posloupností:

nový řádek(LF)'\n'
horizontální tabulátor(HT)'\t'
vertikální tabulátor(VT)'\v'
backspace(BS)'\b'
návrat vozíku(CR)'\r'
nová stránka(FF)'\f'
obrácené lomítko(\)'\\'
apostrof(')'\''
bitový vzorek'\ooo'

Poslední kombinace obráceného lomítka a jedné až tří oktalových číslic ooo udává přímo hodnotu znakové konstanty.

\0, \1, \2,... \377

jsou po řadě všechny bitové kombinace pro znakové konstanty se vzrůstající hodnotou. Znaková konstanta '\0' se zpravidla označuje jako NULL. Uvnitř znakové konstanty se nesmí vyskytnout nový řádek přímo, tj. zápis

'
a
'
není přípustný. Znakové konstanty jsou typu int.

Konstanty v pohyblivé řádové čárce sestávají podle obvyklých konvencí z celočíselné části, desetinné tečky, desetinné části, oddělovače exponentu e nebo E a celočíselného exponentu s volitelným znaménkem. Z této maximální sestavy může scházet buď celočíselná, nebo desetinná část (ne obě). Dále může scházet desetinná tečka nebo exponent včetně e, resp. E (ne obě tyto části). Správný zápis konstanty v pohyblivé čárce, např.

1.45E-4 1. 1e10.785
rozeznáme podle toho, že obsahuje buď desetinnou tečku, nebo exponentovou část (ne obojí). Konstanta v pohyblivé řádové čárce je typu double.

Jména výčtových konstant (odst. 5.4.4) jsou typu int.

Řetězce se zapisují jako posloupnost znaků, uzavřených do uvozovek:

"Toto je řetězec"
kompilátor umístí znaky řetězce do statického pole typu char a přidá jako poslední znak řetězce NULL ('\0'), podle něhož lze najít konec řetězce. Toho se často při zpracování řetězců využívá. Uvnitř řetězce lze psát znaky s grafickou reprezentací nebo znaky podle konvencí pro znakové konstanty, např.:
"Řetězec \n na dva řádky.\n".

Zápis dalších řetězců usnadňuje pravidlo, že dvojice znaků \nový řádek je ignorována, tedy

"Extremne\
dlouhy\
retezec"
je povoleným zápisem řetězce. Všechny řetězce (i se shodným zápisem) jsou považovány za vzájemně odlišné.

5.2.3 Třídy objektů

Jazyk C přiřazuje identifikátoru dva atributy, paměťovou třídu a typ. Paměťová třída určuje prostor a dobu existence paměti spojené s identifikátorem, typ určuje, jak se má interpretovat bitový vzorek v paměti přidělené identifikátoru.

V jazyku C jsou čtyři paměťové třídy:

Vztahují se na objekty pojmenované identifikátory. Mezi objekty nejčastěji patří proměnné (dále to jsou konstanty nebo funkce).

Objekt automatické třídy (dále jen automatický objekt) existuje jen po dobu aktivace bloku, v němž je deklarován. Je v bloku lokální (není viditelný odjinud) a ztrácí svou hodnotu současně s ukončením aktivace bloku.

Statický objekt je lokální v bloku, v němž je deklarován, ale ztrácí svou hodnotu v době mezi aktivacemi tohoto bloku. Existuje tedy po celou dou výpočtu, ale je dostupný jen v dobách aktivace svého bloku. Statické objekty deklarované mimo funkce (tedy implicitně navíc externí) jsou viditelné od své deklarace do konce zdrojového souboru, v němž jsou deklarovány. Používají se tedy pro komunikaci mezi funkcemi téhož zdrojového souboru, nejsou však viditelné z jiných souborů.

Automatické objekty se zpravidla v době výpočtu ukládají na zásobník, statické objekty jsou umístěny v datové části programu.

Externí objekty existují po celou dobu výpočtu a jsou viditelné z celého programu (po té, co byly deklarovány). Mají tedy stejný charakter jako statické objekty, ale nejsou lokální. Používají se pro komunikaci mezi jednotlivými (i separátně kompilovanými) funkcemi.

Registrové objekty mají stejný charakter jako automatické objekty (tj. jsou lokální a existují jen po dobu aktivace svého bloku). Je-li to možné, jsou umístěnyv rychlých registrech procesoru. Jejich maximální počet závisí na použitém technickém vybavení i na kompilátoru.

5.2.4 Typy objektů

Jazyk C podporuje pouze několik základních typů objektů. Znakový objekt (typu char) má dostatek bitů (zpravidla 8) na uchování libovolného znaku z použitého kódu (množiny znaků). Hodnota znakového objektu je celé nezáporné číslo, reprezentující znak v kódu. Znakový objekt však může obsahovat i záporné hodnoty, což závisí na použitém technickém vybavení.

Pro celá čísla (typ int) jsou tři možné reprezentace, označované jako short int, int a long int. Typ int má počet bitů zvolený podle celočíselné aritmetiky procesoru, ostatní typy závisí na implementaci kompilátoru. Typ short int nemá více bitů než int, int nemá více bitů než long int. Všechny ale mohou mít stejný počet bitů. Výčtové typy (enum) jsou identické s některým celočíselným typem nebo jeho podrozsahem.

Celá čísla jsou bez znamének (typ unsigned) jsou určena pro aritmetiku modulo 2n, kde n je počet bitů reprezentace. Tato čísla jsou vždy nezáporná. Objekty typu unsigned odpovídají základním paměťovým strukturám počítače (např. slovo) a používají se zejména tehdy, potřebujeme-li strukturovat slovo do několika částí (viz bitová pole v uniích).

Všechny dosavadní typy jsou považovány za celočíselné. Do aritmetických typů řadíme ještě čísla v pohyblivé řádové čárce jednoduché (typ float) a dvojnásobné (typ double) přesnosti. Obě přesnosti mohou v závislosti na implementaci splynout.

Na základních typech objektů je dobře vidět vývoj jazyka C. Podle návrhu normy lze např. deklarovat objekty typu unsigned char, unsigned long nebo i long double. Poslední jmenovaný objekt je 64 bitové číslo v pohyblivé řádové čárce.

Někdy je třeba vytvořit objekt, který není žádného typu. K tomu existuje prázdný typ void (neobsahuje hodnoty). Typické použití je funkce, vyvolávaná jako procedura, tedy v situaci, kdy není třeba, aby funkce vracela hodnotu. To je případ volání sync jádra (kap. 6), funkce bez parametru, s deklarací

void sync();

Ze základních typů objektů lze neomezeně tvořit odvozené typy pomocí konstrukcí:

Tyto konstrukce mohou být aplikovány vícekrát, i rekurzívně. (čl. 5.4).