You are on page 1of 180

Theory without practice is useless; practice without theory is blind Roger Bacon Limbajul C a fost creat la nceputul anilor

'70 de ctre Brian !ernig"am #i $ennis % Ritc"ie de la Bell Laboratories &e' (erse)* fiind ini+ial destinat scrierii unei pr+i din sistemul de operare ,ni-. Lucrarea /"e C 0rogramming Language a celor doi autori* aprut n mai multe 1ersiuni* a rmas cartea de referin+ n domeniu* impunnd un standard minimal pentru orice implementare. Caracteristicile distincti1e ale limbajului au fost clar definite de la nceput* ele pstrndu2se n toate de31oltrile ulterioare4 5 portabilitate ma-im; 5 structurare; 5 posibilitatea efecturii opera+iilor la ni1elul ma#inii cu pstrarea caracteristicilor unui limbaj e1oluat. 6cest manual este structurat pe 78 capitole astfel nct elementele limbajului C s fie pre3entate ntr2o manier unitar. 0rimul capitol face o scurt introducere #i pre3int patru programe C. ,rmtoarele nou capitole descriu elementele limbajului C. Capitolele unspre3ece #i doispre3ece trec n re1ist func+iile cele mai des utili3ate definite n biblioteca standard* mpreun cu cte1a programe demonstrati1e. 6u fost selectate doar func+iile definite de mai multe standarde 9n primul rnd 6&:; C<* pentru a garanta o portabilitate ct mai mare. 6cest manual a fost conceput pentru a ser1i ca document care s poat fi consultat de programatori n elaborarea proiectelor* #i nu pentru a fi memorat. %anualul nu este o introducere n limbajul C; se presupune c cititorul este familiari3at cu4 5 concepte de ba3 referitoare la programare4 1ariabile* instruc+iuni de atribuire* de control al e-ecu+iei* apeluri de func+ii; 5 repre3entarea informa+iei n calculator a 1alorilor ntregi* n 1irgul mobil* a codurilor 6:C;;; 5 opera+ii de intrare = ie#ire. $eoarece a1em con1ingerea c cea mai bun e-plica+ie este un program func+ional* majoritatea e-emplelor din acest manual se regsesc n fi#iere surs C care pot fi rulate pe orice mediu de programare C #i sub orice sistem de operare. Ca o ultim obser1a+ie amintim recomandarea fcut de n#i#i creatorii limbajului4 cea mai bun metod de n1+are este practica.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

1. Generaliti asupra limbajului C


1.1. Introducere
Limbajul C este un limbaj de programare uni1ersal* caracteri3at printr2o e-primare concis* un control modern al flu-ului e-ecu+iei* structuri de date* #i un bogat set de operatori. Limbajul C nu este un limbaj de ni1el foarte nalt #i nu este speciali3at pentru un anumit domeniu de aplica+ii. 6bsen+a restric+iilor #i generalitatea sa l fac un limbaj mai con1enabil #i mai eficient dect multe alte limbaje mai puternice. Limbajul C permite scrierea de programe bine structurate* datorit construc+iilor sale de control al flu-ului4 grupri de instruc+iuni* luri de deci3ii 9if<* cicluri cu testul de terminare naintea ciclului 9while* for< sau dup ciclu 9do< #i selec+ia unui ca3 dintr2o mul+ime de ca3uri 9switch<. Limbajul C permite lucrul cu pointeri #i are o aritmetic de adrese puternic. Limbajul C nu are opera+ii care prelucrea3 direct obiectele compuse cum snt #irurile de caractere* mul+imile* listele sau masi1ele* considerate fiecare ca o entitate. Limbajul C nu pre3int facilit+i de alocare a memoriei altele dect defini+ia static sau disciplina de sti1 relati1 la 1ariabilele locale ale func+iilor. @n sfr#it* limbajul C nu are facilit+i de intrare2ie#ire #i nici metode directe de acces la fi#iere. /oate aceste mecanisme de ni1el nalt snt reali3ate prin func+ii e-plicite. $e#i limbajul C este* a#adar* un limbaj de ni1el relati1 sc3ut* el este un limbaj agreabil* e-presi1 #i elastic* care se pretea3 la o gam larg de programe. C este un limbaj restrns #i se n1a+ relati1 u#or* iar subtilit+ile se re+in pe msur ce e-perien+a n programare cre#te.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

1.2. Primele programe


@n aceast sec+iune snt pre3entate #i e-plicate patru programe cu scopul de a asigura un suport de ba3 pentru pre3entrile din capitolele urmtoare. 0rin tradi+ie primul program C este un mic e-emplu din lucrarea de1enit clasic 5 /"e C programming language* de Brian !ernig"am #i $ennis % Ritc"ie. #include <stdio.h> main() { printf("Hello, world\n"); return 0; 6cest program afi#ea3 un mesaj de salut. 0rima linie indic faptul c se folosesc func+ii de intrare = ie#ire* #i descrierea modului de utili3are 9numele* tipul argumentelor* tipul 1alorii returnate etc< a acestora se afl n fi#ierul cu numele stdio.h . 6 doua linie declar func+ia main care 1a con+ine instruc+iunile programului. @n acest ca3 singura instruc+iune este un apel al func+iei printf care afi#ea3 un mesaj la terminal. %esajul este dat ntre g"ilimele #i se termin cu un caracter special ne'2line 9 !\n!<. ;nstruc+iunea return pred controlul sistemului de operare la terminarea programului #i comunic acestuia codul 0 pentru terminare. 0rin con1en+ie aceast 1aloare semnific terminarea normal a programului 2 adic nu au aprut erori n prelucrarea datelor. Corpul func+iei main apare ntre acolade. 6l doilea program a#teapt de la terminal introducerea unor numere ntregi nenule #i determin suma lor. @n momentul n care se introduce o 1aloare 3ero* programul afi#ea3 suma calculat. #include <stdio.h> main() { int s,n;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

s " 0; do { scanf("#d",$n); s %" n; while (n&"0); printf("#d\n",s); return 0; @n cadrul func+iei main se declar dou 1ariabile s #i n care 1or memora 1alori ntregi. Cariabila s 9care 1a pstra suma numerelor introduse< este ini+iali3at cu 1aloarea 0. @n continuare se repet o sec1en+ de dou instruc+iuni* prima fiind o opera+ie de intrare #i a doua o adunare. 0rimul argument al func+iei scanf 2 formatul de introducere "#d" 2 indic faptul c se a#teapt introducerea unei 1alori ntregi n format 3ecimal de la terminal 9consol<. 6l doilea argument indic unde se 1a depune n memorie 1aloarea citit; de aceea este necesar s se preci3e3e adresa 1ariabilei n 9cu ajutorul operatorului $<. @n a doua instruc+iune la 1aloarea 1ariabilei s se adun 1aloarea 1ariabilei n. Dperatorul %" are semnifica+ia adun la. 6ceast sec1en+ se repet 9do< ct timp 9while< 1aloarea introdus 9n< este nenul. Dperatorul &" are semnifica+ia diferit de. @n final func+ia printf afi#ea3 pe terminal valoarea 1ariabilei s n format 3ecimal. 6l treilea program a#teapt de la terminal introducerea unei 1alori naturale n* dup care mai a#teapt introducerea a n 1alori reale 9dubl preci3ie<4 a0* a'* ...* an'. @n continuare se parcurge aceast list #i se determin produsul 1alorilor strict po3iti1e. @n final programul afi#ea3 produsul calculat. #include <stdio.h> main() { int n,i; dou(le a)'00*, p;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

scanf("#d",$n); for (i"0; i<n; i%%) scanf("#lf",$a)i*); p " '; for (i"0; i<n; i%%) if (a)i*>0) p +" a)i*; printf("#lf\n",p); return 0; @n cadrul func+iei main se declar dou 1ariabile n #i i care 1or memora 1alori ntregi. Cariabila n pstrea3 numrul de 1alori reale din lista a. :e declar de asemenea un tablou unidimensional a care 1a memora 700 de 1alori de tip real 9dubl preci3ie<* #i o 1ariabil p care 1a memora produsul cerut. :e cite#te de la terminal o 1aloare n. @n continuare se introduc 1alorile reale ai 9i = 0* '* ...* n'<. Formatul de introducere "#lf" indic faptul c se a#teapt introducerea unei 1alori reale de la terminal* care 1a fi depus la loca+ia de memorie asociat 1ariabilei ai. @n locul construc+iei $a)i* se poate folosi forma ec"i1alent a%i. 0entru a introduce toate 1alorile ai se efectuea3 un ciclu for* n cadrul cruia 1ariabila i 9care controlea3 ciclul< ia toate 1alorile ntre 0 9inclusi1< #i n 9e-clusi1< cu pasul '. /recerea la urmtoarea 1aloare a 1ariabilei i se face cu ajutorul operatorului %%. @n continuare 1ariabila p* care 1a memora produsul 1alorilor cerute* se ini+iali3ea3 cu '. Fiecare 1aloare ai este 1erificat 9instruc+iunea if< dac este strict po3iti1 #i n ca3 afirmati1 este nmul+it cu 1aloarea p. Dperatorul +" are semnifica+ia nmulete cu. 6l patrulea program este o ilustrare a unor probleme legate de capacitatea repre3entrilor 1alorilor de tip ntreg #i 1irgul mobil. #include <stdio.h>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

int main() { short ,,i; float a,(,c,u,-,w; i"./0; ,"i+i; printf("#hd\n",,); a"'.0/1234; ("'.0/1235; c"a+a6(+(; u"a+a; -"(+(; w"u6-; printf("#f #f\n",c,w); if (c""w) return 0; else return '; Cariabila ,* care ar trebui s memore3e 1aloarea B7E00* are tipul ntreg scurt 9short<* pentru care domeniul de 1alori este restrns la 5?87EG ?87E7. 6stfel c 1aloarea 777000070000000098< 9n 3ecimal B7E00<* n repre3entare ntreag cu semn este de fapt 57H?E. 6l doilea set de opera+ii necesit o anali3 mai atent; e-plica+iile snt 1alabile pentru programe care rulea3 pe ar"itecturi ;ntel. Cariabila c* care ar trebui s memore3e 1aloarea 8AE7?B7 9re3ultatul corect<* 1a a1ea 1aloarea 8AE7?BE* deoarece tipul float are re3er1ate pentru mantis doar 8A de cifre binare. Re3ultatul este foarte apropiat de cel corect deoarece re3ultatele intermediare se pstrea3 n regi#trii coprocesorului matematic cu preci3ie ma-im. 6bia la memorare se efectuea3 trunc"ierea* de unde re3ult 1aloarea afi#at. Cu totul altfel stau lucrurile n ca3ul celui de al treilea set de opera+ii. 6ici re3ultatele intermediare snt memorate de fiecare dat cu trunc"iere n 1ariabile de tip float. @n final se calculea3 #i diferen+a dintre cele dou 1alori trunc"iate* de unde re3ult 1aloarea 7E77787E. @nainte de terminare se 1erific dac 1alorile c #i w snt egale. @n ca3 afirmati1 se comunic sistemului de operare un cod 0 9terminare normal<. @n ca3 contrar se comunic un cod 7 9terminare anormal<. Rula+i acest program pe diferite sisteme de calcul #i obser1a+i care este re3ultatul.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

1.3. Meta-limbajul i setul de caractere


%eta2limbajul care ser1e#te la descrierea formal a sinta-ei limbajului C este simplu. Categoriile sintactice sau no+iunile care trebuie definite snt urmate de simbolul ' '. $efini+iile alternati1e de categorii snt listate pe linii separate. $ac o linie nu este suficient* se trece la linia urmtoare* aliniat la un tab fa+ de linia precedent. ,n simbol op+ional* terminal sau neterminal este indicat prin adugarea imediat dup el a configura+iei de caractere <opt>. :etul de caractere al limbajului C este un subset al setului de caractere 6:C;;* format din4 5 8E litere mici abcdefg"ijIlmnopJrstu1'-)3 5 8E litere mari 6BC$KFLM;(!L%&D0NR:/,C OPQ 5 70 cifre 078?ABE7GH 5 ?0 simboluri speciale Blanc R S T U V ' 9 < W + * . = 4 ; < = > X Y Z [ \ > ] ^ _ ` 5 E simboluri negrafice Zn* Zt* Zb* Zr* Zf* Za

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

2. !nitile le"icale ale limbajului C


@n limbajul C e-ist #ase tipuri de unit+i le-icale4 identificatori* cu1inte2c"eie* constante* #iruri* operatori #i separatori.

2.1. Identi#icatori
,n identificator este o succesiune de litere #i cifre dintre care primul caracter este n mod obligatoriu o liter. :e admit #i litere mari #i litere mici dar ele se consider caractere distincte. Liniu+a de subliniere > este considerat ca fiind liter. $eci alfabetul peste care snt defini+i identificatorii este urmtorul4 A = <a*...*3*6*...*Q*0*...*H*>>

2.2. Cu$inte c%eie


Cu1intele c"eie snt identificatori re3er1a+i limbajului. Ki au o semnifica+ie bine determinat #i nu pot fi utili3a+i dect a#a cum cere sinta-a limbajului. Cu1intele2c"eie se scriu obligatoriu cu litere mici. 6ceste cu1inte snt 9fiecare mediu de programare C poate folosi #i alte cu1inte re3er1ate<4 int char float dou(le lon7 short unsi7ned re7ister auto e8tern static struct union t9pedef if else for while do continue (rea, const -oid switch case default return si:eof

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70

2.3. Constante
@n limbajul C e-ist urmtoarele tipuri de constante4 ntreg 93ecimal* octal* "e-a3ecimal<* ntreg lung e-plicit* flotant* caracter* simbolic.

Constante &ntregi
D constant ntreag const dintr2o succesiune de cifre. D constant octal este o constant ntreag care ncepe cu 0 9cifra 3ero<* #i este format cu cifre de la 0 la 3. D constant "e-a3ecimal este o constant ntreag precedat de 08 sau 0; 9cifra 0 #i litera 8<. Cifrele "e-a3ecimale includ literele de la < la = #i de la a la f cu 1alori de la '0 la '1. @n orice alt ca3* constanta ntreag este o constant 3ecimal. Exemplu4 constanta 3ecimal 0' poate fi scris ca 003 n octal #i 08'f sau 0;'= n "e-a3ecimal. D constant ntreag este generat pe un cu1nt 9doi sau patru octe+i* dac sistemul de calcul este pe 7E sau ?8 de bi+i<. D constant 3ecimal a crei 1aloare dep#e#te pe cel mai mare ntreg cu semn repre3entabil pe un cu1nt scurt 97E bi+i< se consider de tip lon7 #i este generat pe A octe+i. D constant octal sau "e-a3ecimal care dep#e#te pe cel mai mare ntreg fr semn repre3entabil pe un cu1nt scurt se consider de asemenea de tip lon7. D constant ntreag de1ine negati1 dac i se aplic operatorul unar de negati1are a6a.

Constante de tip e"plicit


D constant ntreag 3ecimal* octal sau "e-a3ecimal* urmat imediat de litera l sau > este o constant lung. 6ceasta 1a fi generat n calculator pe A octe+i. Exemplu4 '.0>.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77

D constant ntreag 3ecimal urmat imediat de litera u sau ? este o constant de tip ntreg fr semn. Litera u sau ? poate fi precedat de litera l sau >. Exemplu4 '.0lu.

Constante #lotante
D constant flotant const dintr2o parte ntreag* un punct 3ecimal* o parte frac+ionar* litera e sau @ #i op+ional* un e-ponent care este un ntreg cu semn. 0artea ntreag #i partea frac+ionar snt constituite din cte o succesiune de cifre. @ntr2o constant flotant* att partea ntreag ct #i partea frac+ionar pot lipsi dar nu ambele; de asemenea poate lipsi punctul 3ecimal sau litera e #i e-ponentul* dar nu deodat 9#i punctul #i litera e #i e-ponentul<. Exemplu4 '.0./12e3 sau 0.'.e0 Drice constant flotant se consider a fi n preci3ie e-tins.

Constante caracter
D constant caracter const dintr2un singur caracter scris ntre apostrofuri* de e-emplu !8!. Caloarea unei constante caracter este 1aloarea numeric a caracterului* n setul de caractere al calculatorului. $e e-emplu n setul de caractere 6:C;; caracterul 3ero sau !0! are 1aloarea /5 n 3ecimal* total diferit de 1aloarea numeric 3ero. Constantele caracter particip la opera+iile aritmetice ca #i oricare alte numere. $e e-emplu* dac 1ariabila c con+ine 1aloarea 6:C;; a unei cifre* atunci prin instruc+iunea4 c " c 6 !0! ; aceast 1aloare se transform n 1aloarea efecti1 a cifrei. 6numite caractere negrafice #i caractere grafice ! 9apostrof< #i \ 9bacIslas"< pot fi repre3entate ca #i constante caracter cu ajutorul a#a numitor sec1en+e de e1itare. :ec1en+ele de e1itare ofer de altfel #i un mecanism general pentru repre3entarea caracterelor mai greu de introdus n calculator #i a oricror configura+ii de bi+i. 6ceste sec1en+e de e1itare snt4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78

\n ne'2line \r carriage return \t tab ori3ontal \f form feed \( bacIspace \a semnal sonor \ddd configura+ie de bi+i 9ddd<

\\ bacIslas" \! apostrof \" g"ilimele

6ceste sec1en+e* de#i snt formate din mai multe caractere* ele repre3int n realitate un singur caracter. :ec1en+a !\ddd! unde ddd este un #ir de 7 pn la ? cifre octale* generea3 pe un octet 1aloarea caracterului dorit sau a configura+iei de bi+i dorite* date de #irul ddd. Exemplu4 sec1en+a !\0/0! 1a genera caracterul spa+iu. ,n ca3 special al acestei construc+ii este sec1en+a !\0! care indic caracterul A?>>* care este caracterul cu 1aloarea 3ero. !\0! este scris deseori n locul lui 0 pentru a sublinia natura de caracter a unei anumite e-presii. Cnd caracterul care urmea3 dup un bacIslas" nu este unul dintre cele specificate* bacIslas"2ul este ignorat. 6tragem aten+ia c toate caracterele setului 6:C;; snt po3iti1e* dar o constant caracter specificat printr2o sec1en+ de e1itare poate fi #i negati1* de e-emplu !\033! are 1aloarea 6'.

Constante simbolice
D constant simbolic este un identificator cu 1aloare de constant. Caloarea constantei poate fi orice #ir de caractere introdus prin construc+ia #define 91e3i capitolul G<. Exemplu4 #define B<; '000 $up ntlnirea acestei construc+ii compilatorul 1a nlocui toate apari+iile constantei simbolice B<; cu 1aloarea '000. &umele constantelor simbolice se scriu de obicei cu litere mari 9fr a fi obligatoriu<.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?

2.'. (iruri
,n #ir este o succesiune de caractere scrise ntre g"ilimele* de e-emplu "<CDE". L"ilimelele nu fac parte din #ir; ele ser1esc numai pentru delimitarea #irului. Caracterul " 9g"ilimele< poate aprea ntr2un #ir dac se utili3ea3 sec1en+a de e1itare \". @n interiorul unui #ir pot fi folosite #i alte sec1en+e de e1itare pentru constante caracter* de asemenea poate fi folosit caracterul \ 9bacIslas"< la sfr#itul unui rnd pentru a da posibilitatea continurii unui #ir pe mai multe linii* situa+ie n care caracterul \ nsu#i 1a fi ignorat. 0entru #irul de caractere se mai folose#te denumirea constant #ir sau constant de tip #ir. Cnd un #ir apare ntr2un program C* compilatorul creea3 un masi1 de caractere care con+ine caracterele #irului #i plasea3 automat caracterul A?>> 9!\0!< la sfr#itul #irului* astfel ca programele care operea3 asupra #irurilor s poat detecta sfr#itul acestora. 6ceast repre3entare nseamn c* teoretic* nu e-ist o limit a lungimii unui #ir* iar programele trebuie s parcurg #irul* anali3ndu2l pentru a2i determina lungimea. :e admit #i #iruri de lungime 3ero. /e"nic* un #ir este un masi1 ale crui elemente snt caractere. Kl are tipul masi1 de caractere #i clasa de memorie static 91e3i sec+iunea ?.7<. ,n #ir este ini+iali3at cu caracterele date 91e3i sec+iunea B.A<. La alocare* memoria fi3ic cerut este cu un octet mai mare dect numrul de caractere scrise ntre g"ilimele* datorit adugrii automate a caracterului null la sfr#itul fiecrui #ir. Exemplu. Func+ia strlen(s) returnea3 lungimea #irului de caractere s* e-clu3nd caracterul terminal null. int strlen(char s)*) { =W returnea3 lungimea #irului W= int i; i"0; while (s)i*&"!\0!) %%i;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A

return i; 6tragem aten+ia asupra diferen+ei dintre o constant caracter #i un #ir care con+ine un singur caracter. "8" nu este acela#i lucru cu !8!. !8! este un singur caracter* folosit pentru a genera pe un octet 1aloarea numeric a literei x* din setul de caractere al calculatorului. "8" este un #ir de caractere* care n calculator se repre3int pe doi octe+i* dintre care primul con+ine un caracter 9litera x<* iar al doilea caracterul A?>> care indic sfr#itul de #ir.

2.). *peratori
Limbajul C pre3int un numr mare de operatori care pot fi clasifica+i dup di1erse criterii. K-ist operatori unari* binari #i ternari* operatori aritmetici* logici* operatori pe bi+i etc. @ntr2un capitol separat 1om pre3enta clasele de operatori care corespund la diferite ni1ele de prioritate.

2.+. ,eparatori
,n separator este un caracter sau un #ir de caractere care separ unit+ile le-icale ntr2un program scris n C. :eparatorul cel mai frec1ent este a#a numitul spa+iu alb 9blanc< care con+ine unul sau mai multe spa+ii* tab2uri* ne'2line2uri sau comentarii. 6ceste construc+ii snt eliminate n fa3a de anali3a le-ical a compilrii. $m mai jos lista separatorilor admi#i n limbajul C. ( ) { ) * 0arante3ele mici ncadrea3 lista de argumente ale unei func+ii sau delimitea3 anumite pr+i n cadrul e-presiilor aritmetice etc 6coladele ncadrea3 instruc+iunile compuse* care constituie corpul unor instruc+iuni sau corpul func+iilor 0arante3ele mari ncadrea3 dimensiunile de masi1 sau
7B

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

" " ! ! ; F+ +F

indicii elementelor de masi1 L"ilimelele ncadrea3 un #ir de caractere 6postrofurile ncadrea3 un singur caracter sau o sec1en+ de e1itare 0unct #i 1irgula termin o instruc+iune :las" asterisc nceput de comentariu 6sterisc slas" sfr#it de comentariu

,n comentariu este un #ir de caractere care ncepe cu caracterele F+ #i se termin cu caracterele +F. ,n comentariu poate s apar oriunde ntr2un program* unde poate aprea un blanc #i are rol de separator; el nu influen+ea3 cu nimic semnifica+ia programului* scopul lui fiind doar o documentare a programului. &u se admit comentarii imbricate.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E

3. -ariabile
D 1ariabil este un obiect de programare cruia i se atribuie un nume. Cariabilele ca #i constantele snt elemente de ba3 cu care operea3 un program scris n C. Cariabilele se deosebesc dup denumire #i pot primi diferite 1alori. &umele 1ariabilelor snt identificatori. &umele de 1ariabile se scriu de obicei cu litere mici 9fr a fi obligatoriu<. Cariabilele n limbajul C snt caracteri3ate prin dou atribute4 clas de memorie #i tip. 6ceste dou atribute i snt atribuite unei 1ariabile prin intermediul unei declara+ii. $eclara+iile listea3 1ariabilele care urmea3 a fi folosite* stabilesc clasa de memorie* tipul 1ariabilelor #i e1entual 1alorile ini+iale* dar despre declara+ii 1om discuta n capitolul B.

3.1. Clase de memorie


Limbajul C pre3int patru clase de memorie4 automatic* e-tern* static* registru.

-ariabile automatice
Cariabilele automatice snt 1ariabile locale fiecrui bloc 9sec+iunea E.8< sau func+ii 9capitolul 7<. Kle se declar prin specificatorul de clas de memorie auto sau implicit prin conte-t. D 1ariabil care apare n corpul unei func+ii sau al unui bloc pentru care nu s2a fcut nici o declara+ie de clas de memorie se consider implicit de clas auto. D 1ariabil auto este actuali3at la fiecare intrare n bloc #i se distruge n momentul cnd controlul a prsit blocul. Kle nu #i re+in 1alorile de la un apel la altul al func+iei sau blocului #i trebuie ini+iali3ate la fiecare intrare. $ac nu snt ini+iali3ate* con+in 1alori
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77

re3iduale. &ici o func+ie nu are acces la 1ariabilele auto din alt func+ie. @n func+ii diferite pot e-ista 1ariabile locale cu acelea#i nume* fr ca 1ariabilele s aib 1reo legtur ntre ele.

-ariabile e"terne
Cariabilele e-terne snt 1ariabile cu caracter global. Kle se definesc n afara oricrei func+ii #i pot fi apelate prin nume din oricare func+ie care intr n alctuirea programului. @n declara+ia de defini+ie aceste 1ariabile nu necesit specificarea nici unei clase de memorie. La ntlnirea unei defini+ii de 1ariabil e-tern compilatorul aloc #i memorie pentru aceast 1ariabil. @ntr2un fi#ier surs domeniul de defini+ie #i ac+iune al unei 1ariabile e-terne este de la locul de declara+ie pn la sfr#itul fi#ierului. 6ceste 1ariabile e-ist #i #i pstrea3 1alorile de2a lungul e-ecu+iei ntregului program. 0entru ca o func+ie s poat utili3a o 1ariabil e-tern* numele 1ariabilei trebuie fcut cunoscut func+iei printr2o declara+ie. $eclara+ia poate fi fcut fie e-plicit prin utili3area specificatorului e-tern* fie implicit prin conte-t. $ac defini+ia unei 1ariabile e-terne apare n fi#ierul surs naintea folosirii ei ntr2o func+ie particular* atunci nici o declara+ie ulterioar nu este necesar* dar poate fi fcut. $ac o 1ariabil e-tern este referit ntr2o func+ie nainte ca ea s fie definit* sau dac este definit ntr2un fi#ier surs diferit de fi#ierul n care este folosit* atunci este obligatorie o declara+ie e-tern pentru a lega apari+iile 1ariabilelor respecti1e. $ac o 1ariabil e-tern este definit ntr2un fi#ier surs diferit de cel n care ea este referit* atunci o singur declara+ie e-tern dat n afara oricrei func+ii este suficient pentru toate func+iile care urmea3 declara+iei. Func+iile snt considerate n general 1ariabile e-terne afar de ca3ul cnd se specific altfel.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7G

Cariabilele e-terne se folosesc adeseori n locul listelor de argumente pentru a comunica date ntre func+ii* c"iar dac func+iile snt compilate separat.

-ariabile statice
Cariabilele statice se declar prin specificatorul de clas de memorie static. 6ceste 1ariabile snt la rndul lor de dou feluri4 interne #i e-terne. Cariabilele statice interne snt locale unei func+ii #i se definesc n interiorul unei func+ii* dar spre deosebire de 1ariabilele auto* ele #i pstrea3 1alorile tot timpul e-ecu+iei programului. Cariabilele statice interne nu snt create #i distruse de fiecare dat cnd func+ia este acti1at sau prsit; ele ofer n cadrul unei func+ii o memorie particular permanent pentru func+ia respecti1. 6lte func+ii nu au acces la 1ariabilele statice interne proprii unei func+ii. Kle pot fi declarate #i implicit prin conte-t; de e-emplu #irurile de caractere care apar n interiorul unei func+ii cum ar fi argumentele func+iei printf 91e3i capitolul 77< snt 1ariabile statice interne. Cariabilele statice e-terne se definesc n afara oricrei func+ii #i orice func+ie are acces la ele. 6ceste 1ariabile snt ns globale numai pentru fi#ierul surs n care ele au fost definite. &u snt recunoscute n alte fi#iere. @n conclu3ie* 1ariabila static este e-tern dac este definit n afara oricrei func+ii #i este static intern dac este definit n interiorul unei func+ii. @n general* func+iile snt considerate obiecte e-terne. K-ist ns #i posibilitatea s declarm o func+ie de clas static. 6ceasta face ca numele func+iei s nu fie recunoscut n afara fi#ierului n care a fost declarat.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7H

-ariabile registru
D 1ariabil registru se declar prin specificatorul de clas de memorie re7ister. Ca #i 1ariabilele auto ele snt locale unui bloc sau func+ii #i 1alorile lor se pierd la ie#irea din blocul sau func+ia respecti1. Cariabilele declarate re7ister indic compilatorului c 1ariabilele respecti1e 1or fi folosite foarte des. $ac este posibil* 1ariabilele re7ister 1or fi plasate de cila static este e-tern dac este definit n afara oricrei func+ii #i este static intern dac este definit n interiorul unei func+ii. @n general* func+iile snt considerate obiecte e-terne. K-ist ns #i posibilitatea s declarm o func+ie de clas re7ister care reflect realitatea "ard'are2ului de ba3. 6stfel4 numai cte1a 1ariabile din fiecare func+ie pot fi pstrate n regi#tri 9de obicei 8 sau ?<; declara+ia register este ignorat pentru celelalte 1ariabile; numai tipurile de date int* char #i pointer snt admise; nu este posibil referirea la adresa unei 1ariabile re7ister.

3.2. .ipuri de $ariabile


Limbajul C admite numai cte1a tipuri fundamentale de 1ariabile4 caracter* ntreg* flotant.

.ipul caracter
D 1ariabil de tip caracter se declar prin specificatorul de tip char. Qona de memorie alocat unei 1ariabile de tip char este de un octet. Ka este suficient de mare pentru a putea memora orice caracter al setului de caractere implementate pe calculator. $ac un caracter din setul de caractere este memorat ntr2o 1ariabil de tip char* atunci 1aloarea sa este egal cu codul ntreg al caracterului respecti1. bi alte cantit+i pot fi memorate n 1ariabile de tip char* dar implementarea este dependent de sistemul de calcul. Drdinul de mrime al 1ariabilelor caracter este ntre 6'.5 #i '.3. Caracterele setului 6:C;; snt toate po3iti1e* dar o constant
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

80

caracter specificat printr2o sec1en+ de e1itare poate fi #i negati1* de e-emplu !\033! are 1aloarea 6'. 6cest lucru se ntmpl atunci cnd aceast constant apare ntr2o e-presie* moment n care se con1erte#te la tipul int prin e-tensia bitului cel mai din stnga din octet 9datorit modului de func+ionare a instruc+iunilor calculatorului<.

.ipul &ntreg
Cariabilele ntregi po3iti1e sau negati1e pot fi declarate prin specificatorul de tip int. Qona de memorie alocat unei 1ariabile ntregi poate fi de cel mult trei dimensiuni. Rela+ii despre dimensiune snt furni3ate de calificatorii short* lon7 #i unsi7ned* care pot fi aplica+i tipului int. Calificatorul short se refer totdeauna la numrul minim de octe+i pe care poate fi repre3entat un ntreg* n ca3ul nostru 8. Calificatorul lon7 se refer la numrul ma-im de octe+i pe care poate fi repre3entat un ntreg* n ca3ul nostru A. /ipul int are dimensiunea natural sugerat de sistemul de calcul. :cara numerelor ntregi repre3entabile n ma#in depinde de asemenea de sistemul de calcul4 un ntreg poate lua 1alori ntre 60.325 #i 0.323 9sisteme de calcul pe 7E bi+i< sau ntre 6.'/3/502/5 #i .'/3/502/3 9sisteme de calcul pe ?8 de bi+i<. Calificatorul unsi7ned alturi de declara+ia de tip int determin ca 1alorile 1ariabilelor astfel declarate s fie considerate ntregi fr semn. &umerele de tipul unsigned respect legile aritmeticii modulo 8 n* unde n este numrul de bi+i din repre3entarea unei 1ariabile de tip int. &umerele de tipul unsi7ned snt totdeauna po3iti1e. $eclara+iile pentru calificatori snt de forma4 short int 8; lon7 int 9; unsi7ned int :; Cu1ntul int poate fi omis n aceste situa+ii.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

87

.ipul #lotant /$irgul mobil0


Cariabilele flotante pot fi n simpl preci3ie #i atunci se declar prin specificatorul de tip float sau n dubl preci3ie #i atunci se declar prin specificatorul dou(le. %ajoritatea sistemelor de calcul admit #i repre3entarea n preci3ie e-tins; o 1ariabil n preci3ie e-tins se declar prin specificatorul lon7 dou(le.

.ipul void /tip nepreci1at0


,n pointer poate fi declarat de tip -oid. @n aceast situa+ie pointerul nu poate fi folosit pentru indirectare 9dereferen+iere< fr un cast e-plicit* #i aceasta deoarece compilatorul nu poate determina mrimea obiectului pe care pointerul l indic. int 8; float r; -oid +p " $8; int main() { +(int +) p " .; p " $r; +(float +)p " '.';

=W p indic pe - W= =W p indic pe r W=

$ac o func+ie este declarat de tip -oid* aceasta nu 1a returna o 1aloare4 -oid hello(char +name) { printf("Hello, #s.",name);

.ipuri deri$ate
@n afar de tipurile aritmetice fundamentale* e-ist* n principiu* o clas infinit de tipuri deri1ate* construite din tipurile fundamentale n urmtoarele moduri4 5 masive de T pentru masi1e de obiecte de un tip dat T* unde T este unul dintre tipurile admise;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

88

5 funcii care returneaz T pentru func+ii care returnea3 obiecte de un tip dat T; 5 pointer la T pentru pointeri la obiecte de un tip dat T; 5 structuri pentru un #ir de obiecte de tipuri diferite; 5 reuniuni care pot con+ine obiecte de tipuri diferite* tratate ntr2o singur 3on de memorie. @n general aceste metode de construire de noi tipuri de obiecte pot fi aplicate recursi1. 6mnunte despre tipurile deri1ate snt date n sec+iunea B.?.

3.3. *biecte i $alori-st&nga


6lte dou no+iuni folosite n descrierea limbajului C snt obiectul #i valoarea-stn a. ,n obiect este con+inutul unei 3one de memorie. D valoare-stn a este o e-presie care se refer la un obiect. ,n e-emplu e1ident de valoare-stn a este un identificator. K-ist operatori care produc 1alori2stnga4 de e-emplu* dac E este o e-presie de tip pointer* atunci +E este o e-presie 1aloare2stnga care se refer la obiectul pe care2l indic E. &umele valoare-stn a 9n limba engle3 left value< a fost sugerat din faptul c n e-presia de atribuire E7 c E8 operandul stng E7 trebuie s fie o e-presie valoare-stn a. @n paragraful de descriere a operatorilor se 1a indica dac operan3ii snt valori-stn a sau dac re3ultatul opera+iei este o valoare-stn a.

3.'. Con$ersii de tip


,n numr mare de operatori pot cau3a con1ersia 1alorilor unui operand de la un tip la altul. $ac ntr2o e-presie apar operan3i de diferite tipuri* ei snt con1erti+i la un tip comun dup un mic numr de reguli. @n general se fac automat numai con1ersiile care an sens* de e-emplu4 din ntreg n flotant* ntr2o e-presie de forma f%i. K-presii care nu au sens* ca de e-emplu un numr flotant ca indice* nu snt admise.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

8?

Caractere i &ntregi
,n caracter poate aprea oriunde unde un ntreg este admis. @n toate ca3urile 1aloarea caracterului este con1ertit automat ntr2un ntreg. $eci ntr2o e-presie aritmetic tipul char #i int pot aprea mpreun. 6ceasta permite o fle-ibilitate considerabil n anumite tipuri de transformri de caractere. ,n astfel de e-emplu este func+ia atoi descris n sec+iunea 7.B care con1erte#te un #ir de cifre n ec"i1alentul lor numeric. K-presia4 s)i* 6 !0! produce 1aloarea numeric a caracterului 9cifr< memorat n 6:C;;. 6tragem aten+ia c atunci cnd o 1ariabil de tip char este con1ertit la tipul int* se poate produce un ntreg negati1* dac bitul cel mai din stnga al octetului con+ine 7. Caracterele din setul de caractere 6:C;; nu de1in niciodat negati1e* dar anumite configura+ii de bi+i memorate n 1ariabile de tip caracter pot aprea ca negati1e prin e-tensia la tipul int. Con1ersia tipului int n char se face cu pierderea bi+ilor de ordin superior. @ntregii de tip short snt con1erti+i automat la int. Con1ersia ntregilor se face cu e-tensie de semn; ntregii snt totdeauna cantit+i cu semn. ,n ntreg lon7 este con1ertit la un ntreg short sau char prin trunc"iere la stnga; surplusul de bi+i de ordin superior se pierde.

Con$ersii #lotante
/oate opera+iile aritmetice n 1irgul mobil se e-ecut n preci3ie e-tins. Con1ersia de la float la int se face prin trunc"ierea pr+ii frac+ionare. Con1ersia de la int la float este acceptat.

2ntregi #r semn

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

8A

@ntr2o e-presie n care apar doi operan3i* dintre care unul unsi7ned iar cellalt un ntreg de orice alt tip* ntregul cu semn este con1ertit n ntreg fr semn #i re3ultatul este un ntreg fr semn. Cnd un int trece n unsi7ned* 1aloarea sa este cel mai mic ntreg fr semn congruent cu ntregul cu semn 9modulo 8 7E sau 8?8<. @ntr2o repre3entare la complementul fa+ de 8 9deci pentru numere negati1e<* con1ersia este conceptual* nu e-ist nici o sc"imbare real a configura+iei de bi+i. Cnd un ntreg fr semn este con1ertit la lon7* 1aloarea re3ultatului este numeric aceea#i ca #i a ntregului fr semn* astfel con1ersia nu face altce1a dect s adauge 3erouri la stnga.

Con$ersii aritmetice
$ac un operator aritmetic binar are doi operan3i de tipuri diferite* atunci tipul de ni1el mai sc3ut este con1ertit la tipul de ni1el mai nalt nainte de opera+ie. Re3ultatul este de tipul de ni1el mai nalt. ;erar"ia tipurilor este urmtoarea4 5 char < short < int < lon7; 5 float < dou(le < lon7 dou(le; 5 tip ntreg cu semn < tip ntreg fr semn; 5 tip ntreg < 1irgul mobil.

Con$ersii prin atribuire


Con1ersiile de tip se pot face prin atribuire; 1aloarea membrului drept este con1ertit la tipul membrului stng* care este tipul re3ultatului.

Con$ersii logice
K-presiile rela+ionale de forma i<G #i e-presiile logice legate prin operatorii $$ #i HH snt definite ca a1nd 1aloarea 7 dac snt ade1rate #i 0 dac snt false. 6stfel atribuirea4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

8B

d " (c>"!0!) $$ (c<"!4!); l face pe d egal cu 7 dac c este cifr #i egal cu 0 n ca3 contrar.

Con$ersii e"plicite
$ac con1ersiile de pn aici le2am putea considera implicite* e-ist #i con1ersii e-plicite de tipuri pentru orice e-presie. 6ceste con1ersii se fac prin construc+ia special numit cast de forma4 (nume-tip) expresie @n aceast construc+ie expresie este con1ertit la tipul specificat dup regulile preci3ate mai sus. %ai precis aceasta este ec"i1alent cu atribuirea e-presiei respecti1e unei 1ariabile de un tip specificat* #i aceast nou 1ariabil este apoi folosit n locul ntregii e-presii. $e e-emplu* n e-presia4 sIrt((dou(le)n) se con1erte#te n la dou(le nainte de a se transmite func+iei sIrt. &otm ns c* con+inutul real al lui n nu este alterat. Dperatorul cast are aceea#i preceden+ ca #i oricare operator unar.

3"presia constant
D e-presie constant este o e-presie care con+ine numai constante. 6ceste e-presii snt e1aluate n momentul compilrii #i nu n timpul e-ecu+iei; ele pot fi astfel utili3ate n orice loc unde sinta-a cere o constant* ca de e-emplu4 #define B<;>JA@ '000 char line)B<;>JA@%'*;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

8E

'. *peratori i e"presii


Limbajul C pre3int un numr mare de operatori* caracteri3a+i prin diferite ni1ele de prioritate sau preceden+. @n acest capitol descriem operatorii n ordinea descresctoare a preceden+ei lor. Dperatorii descri#i n acela#i paragraf au aceea#i preceden+. Com specifica de fiecare dat dac asociati1itatea este la stnga sau la dreapta. K-presiile combin 1ariabile #i constante pentru a produce 1alori noi #i le 1om introduce pe msur ce 1om pre3en+a operatorii.

'.1. 3"presii primare


Expresie-primar4 identificator constant ir (expresie) expresie-primar )expresie* expresie-primar (list-expresii<opt>) valoare-stn a . identificator expresie-primar 6> identificator !ist-expresii4 expresie list-expresii, expresie ,n identificator este o expresie-primar* cu condi+ia c el s fi fost declarat corespun3tor. /ipul su este specificat n declara+ia sa. $ac tipul unui identificator este masiv de ...* atunci 1aloarea expresiei-identificator este un pointer la primul obiect al masi1ului* iar tipul e-presiei este pointer la .... %ai mult* un identificator de masi1 nu este o e-presie valoare-stn a.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

87

La fel* un identificator declarat de tip funcie care returneaz """* care nu apare pe po3i+ie de apel de func+ie este con1ertit la pointer la funcie care returneaz """. D constant este o expresie-primar. /ipul su poate fi int* lon7 sau dou(le. Constantele caracter snt de tip int* constantele flotante snt de tip lon7 dou(le. ,n #ir este o expresie-primar. /ipul su original este masiv de caractere* dar urmnd acelea#i reguli descrise mai sus pentru identificatori* acesta este modificat n pointer la caracter #i re3ultatul este un pointer la primul caracter al #irului. K-ist cte1a e-cep+ii n anumite ini+iali3ri 91e3i paragraful B.A<. D e-presie ntre parante3e rotunde este o expresie-primar* al crei tip #i 1aloare snt identice cu cele ale e-presiei din interiorul parante3elor 9e-presia din parante3e poate fi #i o valoare-stn a<. D expresie-primar urmat de o e-presie ntre parante3e ptrate este o expresie-primar. :ensul intuiti1 este de inde-are. $e obicei expresia-primar are tipul pointer la """* expresia-indice are tipul int* iar re3ultatul are tipul .... D e-presie de forma E7)E8* este identic 9prin defini+ie< cu +((E7)%(E8))* unde + este operatorul de indirectare. ,n apel de func+ie este o expresie-primar. Ka const dintr2o expresie-primar urmat de o perec"e de parante3e rotunde* care con+in o list-expresii separate prin 1irgule. !ista-expresii constituie argumentele reale ale func+iei; aceast list poate fi #i 1id. Expresiaprimar trebuie s fie de tipul funcie care returneaz """* iar re3ultatul apelului de func+ie 1a fi de tipul .... @naintea apelului* oricare argument de tip float este con1ertit la tipul dou(le* oricare argument de tip char sau short este con1ertit la tipul int. &umele de masi1e snt con1ertite n pointeri la nceputul masi1ului. &ici o alt con1ersie nu se efectuea3 automat. $ac este necesar pentru ca tipul unui argument actual s coincid cu cel al argumentului formal* se 1a folosi un cast 91e3i sec+iunea ?.A<. :nt permise apeluri recursi1e la orice func+ie.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

8G

D valoare-stn a urmat de un punct #i un identificator este o expresie-primar. #aloarea-stn a denume#te o structur sau o reuniune 91e3i capitolul 70< iar identificatorul denume#te un membru din structur sau reuniune. Re3ultatul este o valoare-stn a care se refer la membrul denumit din structur sau reuniune. D expresie-primar urmat de o sgeat 9constituit dintr2o liniu+ #i semnul > urmat de un identificator este o expresieprimar. 0rima e-presie trebuie s fie un pointer la o structur sau reuniune* iar identificatorul trebuie s fie numele unui membru din structura sau reuniunea respecti1. Re3ultatul este o valoare-stn a care se refer la membrul denumit din structura sau reuniunea ctre care indic e-presia pointer. K-presia E7>E8 este identic din punctul de 1edere al re3ultatului cu (+E7). E8 $escriem n continuare operatorii limbajului C mpreun cu e-presiile care se pot constitui cu ace#ti operatori.

'.2. *peratori unari


/o+i operatorii unari au aceea#i preceden+* iar e-presiile unare se grupea3 de la dreapta la stnga. Expresie-unar4 + expresie $ valoare-stn a expresie & expresie K expresie %% valoare-stn a 66 valoare-stn a valoare-stn a %% valoare-stn a 66 (nume-tip) expresie si:eof (nume-tip)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

8H

Dperatorul unar + este operatorul de indirectare. K-presia care2l urmea3 trebuie s fie un pointer* iar re3ultatul este o 1aloare2stnga care se refer la obiectul ctre care indic e-presia. $ac tipul e-presiei este pointer la """ atunci tipul re3ultatului este .... 6cest operator tratea3 operandul su ca o adres* face acces la ea #i i ob+ine con+inutul. Exemplu4 instruc+iunea 9 " +p8; atribuie lui 9 con+inutul adresei ctre care indic p8. Dperatorul unar $ este operatorul de ob+inere a adresei unui obiect sau de ob+inere a unui pointer la obiectul respecti1. Dperandul este o valoare-stn a iar re3ultatul este un pointer la obiectul referit de valoarea-stn a. $ac tipul valorii-stn a este ... atunci tipul re3ultatului este pointer la """. Exemplu. Fie 8 o 1ariabil de tip int #i p8 un pointer creat ntr2 un anumit fel 91e3i capitolul H<. 6tunci prin instruc+iunea p8 " $8; se atribuie 1ariabilei de tip pointer la int p8 adresa 1ariabilei 8; putem spune acum c p8 indic spre 8. :ec1en+a4 p8 " $8; 9 " +p8; este ec"i1alent cu 9 " 8; Dperatorul $ poate fi aplicat numai la 1ariabile #i la elemente de masi1. Construc+ii de forma $(8%') #i $0 nu snt admise. $e asemenea nu se admite ca 1ariabila s fie de clas re7ister. Dperatorul unar $ ajut la transmiterea argumentelor de tip adres n func+ii. Dperatorul unar 6 este operatorul de negati1are. Dperandul su este o e-presie* iar re3ultatul este negati1area operandului. @n acest ca3 snt aplicate con1ersiile aritmetice obi#nuite. &egati1area unui ntreg de tip unsigned se face sc3nd 1aloarea sa din 8 n* unde n este numrul de bi+i re3er1a+i tipului int. Dperatorul unar & este operatorul de negare logic. Dperandul su este o e-presie* iar re3ultatul su este 7 sau 0 dup cum 1aloarea operandului este 0 sau diferit de 3ero. /ipul re3ultatului este int.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?0

6cest operator este aplicabil la orice e-presie de tip aritmetic sau la pointeri. Dperatorul unar K 9tilda< este operatorul de complementare la unu. Kl con1erte#te fiecare bit 7 la 0 #i in1ers. Kl este un operator logic pe bi+i. Dperandul su trebuie s fie de tip ntreg. :e aplic con1ersiile aritmetice obi#nuite. Dperatorul unar %% este operatorul de incrementare. Dperandul su este o 1aloare2stnga. Dperatorul produce incrementarea operandului cu 7. 6cest operator pre3int un aspect deosebit deoarece el poate fi folosit ca un operator prefi- 9naintea 1ariabilei4 %%n< sau ca un operator postfi- 9dup 1ariabil4 n%%<. @n ambele ca3uri efectul este incrementarea lui n. $ar e-presia %%n incrementea3 pe n nainte de folosirea 1alorii sale* n timp ce n%% incrementea3 pe n dup ce 1aloarea sa a fost utili3at. 6ceasta nseamn c n conte-tul n care se urmre#te numai incrementarea lui n* oricare construc+ie poate fi folosit* dar ntr2un conte-t n care #i 1aloarea lui n este folosit %%n #i n%% furni3ea3 dou 1alori distincte. Exemplu4 dac n este B* atunci 8 " n%% ; atribuie lui 8 1aloarea B 8 " %%n ; atribuie lui 8 1aloarea E @n ambele ca3uri n de1ine E. Re3ultatul opera+iei nu este o valoare-stn a* dar tipul su este tipul valorii-stn a. Dperatorul unar 66 este operatorul de decrementare. 6cest operator este analog cu operatorul %% doar c produce decrementarea cu 7 a operandului. Dperatorul (nume-tip) este operatorul de con1ersie de tip. 0rin nume-tip n+elegem unul dintre tipurile fundamentale admise n C. Dperandul acestui operator este o expresie. Dperatorul produce con1ersia 1alorii expresiei la tipul denumit. 6ceast construc+ie se nume#te cast. Dperatorul si:eof furni3ea3 dimensiunea n octe+i a operandului su. 6plicat unui masi1 sau structuri* re3ultatul este
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?7

numrul total de octe+i din masi1 sau structur. $imensiunea se determin n momentul compilrii* din declara+iile obiectelor din e-presie. :emantic* aceast e-presie este o constant ntreag care se poate folosi n orice loc n care se cere o constant. Cea mai frec1ent utili3are o are n comunicarea cu rutinele de alocare a memoriei sau rutinele ;=D sistem. Dperatorul si:eof poate fi aplicat #i unui nume-tip ntre parante3e. @n acest ca3 el furni3ea3 dimensiunea n octe+i a unui obiect de tipul indicat. Construc+ia si:eof(nume-tip) este luat ca o unitate* astfel c e-presia si:eof(nume-tip)6. este acela#i lucru cu (si:eof(nume-tip))6.

'.3. *peratori multiplicati$i


Dperatorii multiplicati1i + F #i # snt operatori aritmetici binari #i se grupea3 de la stnga la dreapta. Expresie-multiplicativ4 expresie + expresie expresie F expresie expresie # expresie Dperatorul binar + indic nmul+irea. Dperatorul este asociati1* dar n e-presiile n care apar mai mul+i operatori de nmul+ire* ordinea de e1aluare nu se specific. Compilatorul rearanjea3 c"iar #i un calcul cu parante3e. 6stfel a+((+c) poate fi e1aluat ca (a+()+c. 6ceasta nu implic diferen+e* dar dac totu#i se dore#te o anumit ordine* atunci se 1or introduce 1ariabile temporare. Dperatorul binar F indic mpr+irea. Cnd se mpart dou numere ntregi po3iti1e* trunc"ierea se face spre 3ero; dac unul dintre operan3i este negati1 atunci trunc"ierea depinde de sistemul de calcul.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?8

Dperatorul binar # furni3ea3 restul mpr+irii primei e-presii la cea de a doua. Dperan3ii nu pot fi de tip float. Restul are totdeauna semnul dempr+itului. /otdeauna (aF()+(%a#( este egal cu a 9dac ( este diferit de 0<. :nt e-ecutate con1ersiile aritmetice obi#nuite.

'.'. *peratori aditi$i


Dperatorii aditi1i % #i 6 snt operatori aritmetici binari #i se grupea3 de la stnga la dreapta. :e e-ecut con1ersiile aritmetice obi#nuite* Expresie-aditiv4 expresie % expresie expresie 6 expresie Dperatorul binar % produce suma operan3ilor si. Kl este asociati1 #i e-presiile care con+in mai mul+i operatori pot fi rearanjate la fel ca n ca3ul operatorului de nmul+ire. Dperatorul binar 6 produce diferen+a operan3ilor si.

'.). *peratori de deplasare


Dperatorii de deplasare << #i >> snt operatori logici pe bi+i. Ki se grupea3 de la stnga la dreapta. Expresie-deplasare4 expresie << expresie expresie >> expresie Dperatorul << produce deplasarea la stnga a operandului din stnga cu un numr de po3i+ii binare dat de operandul din dreapta. Dperatorul >> produce deplasarea la dreapta a operandului din stnga cu un numr de po3i+ii binare dat de operandul din dreapta. @n ambele ca3uri se e-ecut con1ersiile aritmetice obi#nuite asupra operan3ilor* fiecare dintre ei trebuind s fie de tip ntreg. Dperandul din dreapta este con1ertit la int; tipul re3ultatului este
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

??

cel al operandului din stnga. Re3ultatul este nedefinit dac operandul din dreapta este negati1 sau mai mare sau egal cu lungimea obiectului* n bi+i. 6stfel 1aloarea e-presiei E7<<E8 este E7 9interpretat ca #i configura+ie de bi+i< deplasat la stnga cu E8 po3i+ii bit; bi+ii elibera+i de1in 3ero. K-presia E7>>E8 este E7 deplasat la dreapta cu E8 po3i+ii binare. $eplasarea la dreapta este logic 9bi+ii elibera+i de1in 0< dac E7 este de tip unsigned; altfel ea este aritmetic 9bi+ii elibera+i de1in copii ale bitului semn<. Exemplu4 8<<. deplasea3 pe 8 la stnga cu 8 po3i+ii* bi+ii elibera+i de1in 0; aceasta este ec"i1alent cu multiplicarea lui 8 cu A.

'.+. *peratori relaionali


Dperatorii rela+ionali <* >* <"* >" se grupea3 de la stnga la dreapta. Expresie-relaional4 expresie < expresie expresie > expresie expresie <" expresie expresie >" expresie Dperatorii < 9mai mic<* > 9mai mare<* <" 9mai mic sau egal< #i >" 9mai mare sau egal< produc 1aloarea 0 dac rela+ia specificat este fals #i 7 dac ea este ade1rat. /ipul re3ultatului este int. :e e-ecut con1ersiile aritmetice obi#nuite. 6ce#ti operatori au preceden+a mai mic dect operatorii aritmetici* astfel c e-presia i<86' se consider i<(86') a#a dup cum ne a#teptam.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?A

'.4. *peratori de egalitate


Expresie-e alitate4 expresie "" expresie expresie &" expresie Dperatorii "" 9egal cu< #i &" 9diferit de< snt analogi cu operatorii rela+ionali* dar preceden+a lor este mai mic. 6stfel a<( "" c<d este 7* dac a<( #i c<d au aceea#i 1aloare de ade1r.

'.5. *peratorul I pe bii


Expresie-$%4 expresie $ expresie Dperatorul $ este operatorul $% logic pe bi+i. Kl este asociati1 #i e-presiile care con+in operatorul $ pot fi rearanjate. Re3ultatul este func+ia logic $% pe bi+i aplicat operan3ilor si. Dperatorul se aplic numai la operan3i de tipuri ntregi. Legea dup care func+ionea3 este4 V 0 7 0 0 0 7 0 7

Dperatorul $ este deseori folosit pentru a masca o anumit mul+ime de bi+i4 de e-emplu4 c " n $ 0'33; pune pe 3ero to+i bi+ii afar de ultimii 7 bi+i de ordin inferior ai lui n* fr a afecta con+inutul lui n.

'.6. *peratorul SAU-exclusiv pe bii


Expresie-&A'-exclusiv4 expresie L expresie Dperatorul L este operatorul &A'-exclusiv logic pe bi+i. Kl este asociati1 #i e-presiile care2l con+in pot fi rearanjate. Re3ultatul este
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?B

func+ia logic &A'-exclusiv pe bi+i aplicat operan3ilor si. Dperatorul se aplic numai la operan3i de tipuri ntregi. Legea dup care func+ionea3 este4 L 0 7 0 0 7 7 7 0

'.17. *peratorul SAU-inclusiv pe bii


Expresie-&A'-inclusiv4 expresie H expresie Dperatorul H este operatorul &A'-inclusiv logic pe bi+i. Kl este asociati1 #i e-presiile care2l con+in pot fi rearanjate. Re3ultatul este func+ia logic &A'-inclusiv pe bi+i aplicat operan3ilor si. Dperatorul se aplic numai la operan3i de tipuri ntregi. Legea dup care func+ionea3 este4 H 0 7 0 0 7 7 7 7

Dperatorul H este folosit pentru a po3i+iona bi+i; de e-emplu4 8 " 8 H B<MN; pune pe 7 to+i bi+ii din 8 care corespund la bi+i po3i+iona+i pe 7 din B<MN. :e efectuea3 con1ersiile aritmetice obi#nuite.

'.11. *peratorul I-logic


Expresie-$%-lo ic4 expresie $$ expresie Dperatorul $$ este operatorul $%-lo ic #i el se grupea3 de la stnga la dreapta. Re3ultatul este 7 dac ambii operan3i snt diferi+i de 3ero #i 0 n rest. :pre deosebire de operatorul $% pe bi+i $* operatorul
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?E

$%-lo ic $$ garantea3 o e1aluare de la stnga la dreapta; mai mult* al doilea operand nu este e1aluat dac primul operand este 0. Dperan3ii nu trebuie s aib n mod obligatoriu acela#i tip* dar fiecare trebuie s aib unul dintre tipurile fundamentale sau pointer. Re3ultatul este totdeauna de tip int.

'.12. *peratorul SAU-logic


Expresie-&A'-lo ic4 expresie HH expresie Dperatorul HH este operatorul &A'-lo ic #i el se grupea3 de la stnga la dreapta. Re3ultatul este 7 dac cel pu+in unul dintre operan3i este diferit de 3ero #i 0 n rest. :pre deosebire de operatorul &A'-inclusiv pe bi+i H* operatorul &A'-lo ic HH garantea3 o e1aluare de la stnga la dreapta; mai mult* al doilea operand nu este e1aluat dac 1aloarea primului operand este diferit de 3ero. Dperan3ii nu trebuie s aib n mod obligatoriu acela#i tip* dar fiecare trebuie s aib unul dintre tipurile fundamentale sau pointer. Re3ultatul este totdeauna de tip int.

'.13. *peratorul condiional


Expresie-condiional4 expresie O expresie 4 expresie Dperatorul condi+ional O este un operator ternar. 0rima e-presie se e1aluea3 #i dac ea este diferit de 3ero sau ade1rat* re3ultatul este 1aloarea celei de2a doua e-presii* altfel re3ultatul este 1aloarea e-presiei a treia. $e e-emplu e-presia4 : " (a>() O a P (; calculea3 ma-imul dintre a #i ( #i l atribuie lui :. :e e1aluea3 mai nti prima e-presie a>(. $ac ea este ade1rat se e1aluea3 a doua e-presie #i 1aloarea ei este re3ultatul opera+iei* aceast 1aloare se
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?7

atribuie lui :. $ac prima e-presie nu este ade1rat atunci : ia 1aloarea lui (. K-presia condi+ional poate fi folosit peste tot unde sinta-a cere o e-presie. $ac este posibil* se e-ecut con1ersiile aritmetice obi#nuite pentru a aduce e-presia a doua #i a treia la un tip comun; dac ambele e-presii snt pointeri de acela#i tip* re3ultatul are #i el acela#i tip; dac numai o e-presie este un pointer* cealalt trebuie sa fie constanta 0* iar re3ultatul este de tipul pointerului. @ntotdeauna numai una dintre e-presiile a doua #i a treia este e1aluat. $ac f este flotant #i n ntreg* atunci e-presia (h>0)O f P n este de tip double indiferent dac n este po3iti1 sau negati1. 0arante3ele nu snt necesare deoarece preceden+a operatorului OP este mai mic* dar ele pot fi folosite pentru a face e-presia condi+ional mai 1i3ibil.

'.1'. *peratori de atribuire


K-ist mai mul+i operatori de atribuire* care se grupea3 to+i de la dreapta la stnga. Dperandul stng este o 1aloare2stnga* operandul drept este o e-presie. /ipul e-presiei de atribuire este tipul operandului stng. Re3ultatul este 1aloarea memorat n operandul stng dup ce atribuirea a a1ut loc. Cele dou pr+i ale unui operator de atribuire compus snt unit+i le-icale 9simboluri< distincte. Expresie-atribuire4 valoare-stn a " expresie valoare-stn a op" expresie unde op poate fi unul din operatorii %* 6* +* F* #* <<* >>* $* L* H. @ntr2o atribuire simpl cu "* 1aloarea e-presiei nlocuie#te pe cea a obiectului referit de valoare-stn a. $ac ambii operan3i au tip aritmetic* atunci operandul drept este con1ertit la tipul operandului stng nainte de atribuire.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?G

K-presiile de forma E7 op" E8 se interpretea3 ca fiind ec"i1alente cu e-presiile de forma E7 " E7 op E8; totu#i E7 este e1aluat o singur dat. Exemplu4 e-presia 8 +" 9%' este ec"i1alent cu 8 " 8 + (9%') #i nu cu 8 " 8 + 9 % ' 0entru operatorii %" #i 6"* operandul stng poate fi #i un pointer* n care ca3 operandul din dreapta este con1ertit la ntreg 91e3i capitolul H<. /o+i operan3ii din dreapta #i to+i operan3ii din stnga care nu snt pointeri trebuie s fie de tip aritmetic. 6tribuirea prescurtat este a1antajoas n ca3ul cnd n membrul stng a1em e-presii complicate* deoarece ele se e1aluea3 o singur dat.

'.1). *peratorul $irgul


Expresie-vir ul4 expresie , expresie D perec"e de e-presii separate prin 1irgul se e1aluea3 de la stnga la dreapta #i 1aloarea e-presiei din stnga se neglijea3. /ipul #i 1aloarea re3ultatului snt cele ale operandului din dreapta. 6ce#ti operatori se grupea3 de la stnga la dreapta. @n conte-tele n care 1irgula are un sens special* 9de e-emplu ntr2o list de argumente reale ale unei func+ii #i lista de ini+iali3are<* operatorul 1irgul descris aici poate aprea numai n parante3e. $e e-emplu func+ia4 f(a,(t"0,t%.),c) are trei argumente* dintre care al doilea are 1aloarea B. K-presia acestui argument este o e-presie 1irgul. @n calculul 1alorii lui se e1aluea3 nti e-presia din stnga #i se ob+ine 1aloarea ? pentru t* apoi cu aceast 1aloare se e1aluea3 a doua e-presie #i se ob+ine t=B. 0rima 1aloare a lui t se pierde.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

?H

'.1+. Precedena i ordinea de e$aluare


/abelul de la sfr#itul acestei sec+iuni constituie un re3umat al regulilor de preceden+ #i asociati1itate ale tuturor operatorilor. Dperatorii din aceea#i linie au aceea#i preceden+; liniile snt scrise n ordinea descresctoare a preceden+ei* astfel de e-emplu operatorii +* F #i # au to+i aceea#i preceden+* care este mai mare dect aceea a operatorilor % #i 6. $up cum s2a men+ionat deja* e-presiile care con+in unul dintre operatorii asociati1i sau comutati1i 9 +* %* $* L* H< pot fi rearanjate de compilator c"iar dac con+in parante3e. @n cele mai multe ca3uri aceasta nu produce nici o diferen+; n ca3urile n care o asemenea diferen+ ar putea aprea pot fi utili3ate 1ariabile temporare e-plicite* pentru a for+a ordinea de e1aluare. Limbajul C* ca #i multe alte limbaje* nu specific n ce ordine snt e1alua+i operan3ii unui operator. $e e-emplu ntr2o instruc+iune de forma4 8 " f() % 7(); f poate fi e1aluat nainte sau dup e1aluarea lui 7; dac f sau 7 alterea3 o 1ariabil e-tern de care cealalt depinde* 8 poate depinde de ordinea de e1aluare. $in nou re3ultate intermediare trebuie memorate n 1ariabile temporare pentru a asigura o sec1en+ particular.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

A0

Dperator () )* 6> . & %% 66 6 (tip) + $ si:eof + F # % 6 << >> < <" > >" "" &" $ L H $$ HH OP " op" ,

6sociati1itate stnga la dreapta dreapta la stnga stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta stnga la dreapta dreapta la stnga dreapta la stnga stnga la dreapta

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

A7

). 8eclaraii
$eclara+iile se folosesc pentru a specifica interpretarea pe care compilatorul trebuie s o dea fiecrui identificator. (eclaraie4 specificator-declaraie lista-declarator<opt>; &pecificator-declaraie4 specificator-tip specificator-declaraie<opt> specificator-clas-memorie specificator-declaraie<opt> &pecificator-tip4 char short int lon7 unsi7ned float dou(le -oid specificator-structur-sau-reuniune t9pedef-nume &pecificator-clas-memorie4 auto static e8tern re7ister const t9pedef !ista-declarator4 declarator-cu-iniializare declarator-cu-iniializare* lista-declarator (eclarator-cu-iniializare4 declarator iniializator<opt> (eclarator4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

A8

identificator (declarator) + declarator declarator () declarator )expresie-constant<opt>* $eclara+iile listea3 toate 1ariabilele care urmea3 a fi folosite ntr2un program. D declara+ie specific tipul* clasa de memorie #i e1entual 1alorile ini+iale pentru una sau mai multe 1ariabile de acela#i tip. $eclara+iile se fac sau n afara oricrei func+ii sau la nceputul unei func+ii naintea oricrei instruc+iuni. &u orice declara+ie re3er1 #i memorie pentru un anumit identificator* de aceea deosebim4 declara+ia de defini+ie a unei 1ariabile* care se refer la locul unde este creat 1ariabila #i unde i se aloc memorie; declara+ia de utili3are a unei 1ariabile* care se refer la locul unde numele 1ariabilei este declarat pentru a anun+a propriet+ile 1ariabilei care urmea3 a fi folosit.

).1. ,peci#icatori de clas de memorie


:pecificatorii de clas de memorie snt4 auto static e8tern const t9pedef re7ister

:pecificatorul t9pedef nu re3er1 memorie #i este denumit specificator de clas de memorie numai din moti1e sintactice; el 1a fi discutat n capitolul 70. :emnifica+ia diferitelor clase de memorie a fost discutat deja n paragraful ?.7. $eclara+iile cu specificatorii auto* static #i re7ister determin #i re3er1area unei 3one de memorie corespun3toare. $eclara+ia cu specificatorul e8tern presupune o defini+ie e-tern pentru identificatorii da+i* unde1a n afara func+iei sau fi#ierului n care ei snt declara+i.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

A?

@ntr2o declara+ie poate s apar cel mult un specificator de clas de memorie. $ac specificatorul de clas lipse#te din declara+ie* el se consider implicit auto n interiorul unei func+ii #i defini+ie e-tern n afara func+iei. K-cep+ie fac func+iile care nu snt niciodat automatice. $e e-emplu liniile4
int sp; dou(le -al)B<;Q<>*;

care apar ntr2un program n afara oricrei func+ii* definesc 1ariabilele e-terne sp de tip int #i -al de tip masi1 de dou(le. Kle determin alocarea memoriei #i ser1esc de asemenea ca declara+ii ale acestor 1ariabile n tot restul fi#ierului surs. 0e de alt parte liniile4
e8tern int sp; e8tern dou(le -al)*;

declar pentru restul fi#ierului surs c 1ariabilele sp #i -al snt e-terne* sp este de tip int #i -al este un masi1 de dou(le #i c ele au fost definite n alt parte* unde li s2a alocat #i memorie. $eci aceste declara+ii nu creea3 aceste 1ariabile #i nici nu le aloc memorie.

).2. ,peci#icatori de tip


:pecificatorii de tip snt4 char short int lon7 float dou(le -oid specificator-structur-sau-reuniune t9pedef2nume unsi7ned

Cu1intele lon7* short #i unsi7ned pot fi considerate #i ca adjecti1e; urmtoarele combina+ii snt acceptate4 short int lon7 int unsi7ned int unsi7ned lon7 int lon7 dou(le
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

AA

@ntr2o declara+ie se admite cel mult un specificator de tip* cu e-cep+ia combina+iilor amintite mai sus. $ac specificatorul de tip lipse#te din declara+ie* el se consider implicit int. :pecificatorii de structuri #i reuniuni snt pre3enta+i n sec+iunea 70.H* iar declara+iile cu t9pedef n sec+iunea 70.70.

).3. 8eclaratori
!ista-declarator care apare ntr2o declara+ie este o succesiune de declaratori separa+i prin 1irgule* fiecare dintre ei putnd a1ea un ini+iali3ator. $eclaratorii din lista-declarator snt identificatorii care trebuie declara+i. Fiecare declarator este considerat ca o afirma+ie care* atunci cnd apare o construc+ie de aceea#i form cu declaratorul* produce un obiect de tipul #i de clasa de memorie indicat. Fiecare declarator con+ine un singur identificator. Lruparea declaratorilor este la fel ca #i la e-presii. $ac declaratorul este un identificator simplu* atunci el are tipul indicat de specificatorul din declara+ie. ,n declarator ntre parante3e este tot un declarator* dar legtura declaratorilor complec#i poate fi alterat de parante3e. : considerm acum o declara+ie de forma4 T (7 unde T este un specificator de tip 9ca de e-emplu int< #i (7 un declarator. : presupunem c aceast declara+ie face ca identificatorul s aib tipul ... T unde ... este 1id dac (7 este un identificator simplu 9a#a cum tipul lui 8 n int 8 este int<. $ac (7 are forma4 +( atunci tipul identificatorului pe care2l con+ine acest declarator este pointer la T. $ac (7 are forma4 (()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

AB

atunci identificatorul pe care2l con+ine are tipul funcie care returneaz T. $ac (7 are forma4 ()expresie-constant* sau ()* atunci identificatorul pe care2l con+ine are tipul masiv de T. @n primul ca3 e-presia constant este o e-presie a crei 1aloare este determinabil la compilare #i al crei tip este int. Cnd mai mul+i identificatori masiv de T snt adiacen+i* se creea3 un masi1 multidimensional; e-presiile constante care specific marginile masi1elor pot lipsi numai pentru primul membru din sec1en+. 6ceast omisiune este util cnd masi1ul este e-tern #i defini+ia real care aloc memoria este n alt parte 91e3i sec+iunea B.7<. 0rima e-presie constant poate lipsi de asemenea cnd declaratorul este urmat de ini+iali3are. @n acest ca3 dimensiunea este calculat la compilare din numrul elementelor ini+iale furni3ate. ,n masi1 poate fi construit din obiecte de unul dintre tipurile de ba3* din pointeri* din reuniuni sau structuri* sau din alte masi1e 9pentru a genera un masi1 multidimensional<. &u toate posibilit+ile admise de sinta-a de mai sus snt permise. Restric+iile snt urmtoarele4 func+iile nu pot returna masi1e* structuri* reuniuni sau func+ii* de#i ele pot returna pointeri la astfel de obiecte; nu e-ist masi1e de func+ii* dar pot fi masi1e de pointeri la func+ii. $e asemenea* o structur sau reuniune nu poate con+ine o func+ie* dar ea poate con+ine un pointer la func+ie. $e e-emplu* declara+ia int i, +ip, f(), +fip(), (+pfi)(); declar un ntreg i* un pointer ip la un ntreg* o func+ie f care returnea3 un ntreg* o func+ie fip care returnea3 un pointer la un ntreg* un pointer pfi la o func+ie care returnea3 un ntreg. 0re3int interes compararea ultimilor doi declaratori. Construc+ia +fip() este +(fip())* astfel c declara+ia sugerea3 apelul func+iei fip #i apoi utili3nd indirectarea prin intermediul pointerului se ob+ine un ntreg.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

AE

@n declaratorul (+pfi)()* parante3ele e-terne snt necesare pentru arta c indirectarea printr2un pointer la o func+ie furni3ea3 o func+ie* care este apoi apelat; ea returnea3 un ntreg. $eclara+iile de 1ariabile pot fi e-plicite sau implicite prin conte-t. $e e-emplu declara+iile4 int a,(,c; char d, m)'00*; specific un tip #i o list de 1ariabile. 6ici clasa de memorie nu este declarat e-plicit* ea se deduce din conte-t. $ac declara+ia este fcut n afara oricrei func+ii atunci clasa de memorie este e8tern; dac declara+ia este fcut n interiorul unei func+ii atunci implicit clasa de memorie este auto. Cariabilele pot fi distribuite n declara+ii n orice mod; astfel listele le mai sus pot fi scrise #i sub forma4 int a; int (; int c; char d; char m)'00*; 6ceasta ultim form ocup mai mult spa+iu dar este mai con1enabil pentru adugarea unui comentariu pentru fiecare declara+ie sau pentru modificri ulterioare.

).'. Modi#icatorul const


Caloarea unei 1ariabile declarate cu acest modificator nu poate fi modificat. :inta-a4 const nume-variabil " valoare ; nume-funcie (...* const tip +nume-variabil* ...) @n prima 1ariant* modificatorul atribuie o 1aloare ini+ial unei 1ariabile care nu mai poate fi ulterior modificat de program. $e e-emplu* const int -irsta " 04; Drice atribuire pentru 1ariabila -irsta 1a genera o eroare de compilare.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

A7

6ten+ieR D 1ariabil declarat cu const poate fi indirect modificat prin intermediul unui pointer4 int +p " $-irsta; +p " 01; @n a doua 1ariant modificatorul const este folosit mpreun cu un parametru pointer ntr2o list de parametri ai unei func+ii. Func+ia nu poate modifica 1ariabila pe care o indic pointerul4 int printf (const char +format, ...);

).). Iniiali1are
,n declarator poate specifica o 1aloare ini+ial pentru identificatorul care se declar. ;ni+iali3atorul este precedat de semnul " #i const dintr2o e-presie sau o list de 1alori incluse n acolade. %niializator4 expresie {list-iniializare !ist-iniializare4 expresie list-iniializare, list-iniializare {list-iniializare /oate e-presiile dintr2un iniializator pentru 1ariabile statice sau e-terne trebuie s fie e-presii constante 91e3i sec+iunea ?.A< sau e-presii care se reduc la adresa unei 1ariabile declarate anterior* posibil offset2ul unei e-presii constante. Cariabilele de clas auto sau register pot fi ini+iali3ate cu e-presii oarecare* nu neaprat e-presii constante* care implic constante sau 1ariabile declarate anterior sau c"iar func+ii. @n absen+a ini+iali3rii e-plicite* 1ariabilele statice #i e-terne snt ini+iali3ate implicit cu 1aloarea 0. Cariabilele auto #i register au 1alori ini+iale nedefinite 9re3iduale<. 0entru 1ariabilele statice #i e-terne* ini+iali3area se face o singur dat* n principiu nainte ca programul s nceap s se e-ecute.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

AG

0entru 1ariabilele auto #i re7ister* ini+iali3area este fcut la fiecare intrare n func+ie sau bloc. $ac un ini+iali3ator se aplic unui scalar 9un pointer sau un obiect de tip aritmetic< el const dintr2o singur e-presie* e1entual n acolade. Caloarea ini+ial a obiectului este luat din e-presie; se efectuea3 acelea#i opera+ii ca n ca3ul atribuirii. 0entru ini+iali3area masi1elor #i masi1elor de pointeri 1e3i sec+iunea H.G. 0entru ini+iali3area structurilor 1e3i sec+iunea 70.?. $ac masi1ul sau structura con+ine sub2masi1e sau sub2structuri regula de ini+iali3are se aplic recursi1 la membrii masi1ului sau structuri.

).+. Nume-tip
@n cele e-puse mai sus furni3area unui nume-tip a fost necesar n dou conte-te4 pentru a specifica con1ersii e-plicite de tip prin intermediul unui cast 91e3i sec+iunea ?.A<; ca argument al lui si:eof 91e3i sec+iunea A.8<. ,n nume-tip este n esen+ o declara+ie pentru un obiect de acest tip* dar care omite numele obiectului. )ume-tip4 specificator-tip declarator-abstract (eclarator-abstract4 vid (declarator-abstract) +declarator-abstract declarator-abstract() declarator-abstract)expresie-constant<opt>* 0entru a e1ita ambiguitatea* n construc+ia4 (declarator-abstract) declaratorul abstract se presupune a nu fi 1id. Cu aceast restric+ie* este posibil s identificm n mod unic locul ntr2un declaratorabstract* unde ar putea aprea un identificator* dac aceast
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

AH

construc+ie a fost un declarator ntr2o declara+ie. 6tunci tipul denumit este acela#i ca #i tipul identificatorului ipotetic. $e e-emplu4 int int+ int +)0* int(+))0* int +( ) int(+)() denume#te respecti1 tipurile int* pointer la ntre * masiv de ? pointeri la ntre i* pointer la un masiv de ? ntre i* funcie care returneaz pointer la ntre #i pointer la o funcie care returneaz ntre .

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

B0

+. Instruciuni
@ntr2un program scris n limbajul C instruc+iunile se e-ecut sec1en+ial* n afar de ca3ul n care se indic altfel. ;nstruc+iunile pot fi scrise cte una pe o linie pentru o li3ibilitate mai bun* dar nu este obligatoriu.

+.1. Instruciunea expresie


Cele mai multe instruc+iuni snt instruc+iuni expresie. D e-presie de1ine instruc+iune dac ea este urmat de punct #i 1irgul. Format4 expresie; $e obicei instruc+iunile expresie snt atribuiri sau apeluri de func+ie; de e-emplu4 8 " 0; printf(...); @n limbajul C punct #i 1irgula este un terminator de instruc+iune #i este obligatoriu.

+.2. Instruciunea compus sau blocul


;nstruc+iunea compus este o grupare de declara+ii #i instruc+iuni nc"ise ntre acolade. Kle au fost introduse cu scopul de a folosi mai multe instruc+iuni acolo unde sinta-a cere o instruc+iune. ;nstruc+iunea compus sau blocul snt ec"i1alente sintactic cu o singur instruc+iune. Format4 %nstruciune-compus4 { list-declaratori<opt> list-instruciuni<opt> !ist-declaratori4 declaraie declaraie list-declaratori
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

B7

!ist-instruciuni4 instruciune instruciune list-instruciuni $ac anumi+i identificatori din lista-declaratori au fost declara+i anterior* atunci declara+ia e-terioar este sal1at pe durata blocului* dup care #i reia sensul su. Drice ini+iali3are pentru 1ariabile auto #i re7ister se efectuea3 la fiecare intrare n bloc. ;ni+iali3rile pentru 1ariabilele static se e-ecut numai o singur dat cnd programul ncepe s se e-ecute. ,n bloc se termin cu o acolad dreapt care nu este urmat niciodat de punct #i 1irgul.

+.3. Instruciunea condiional


:inta-a instruc+iunii condi+ionale admite dou formate4 if (expresie) instruciune27 if (expresie) instruciune27 else instruciune28 ;nstruc+iunea condi+ional se folose#te pentru a lua deci3ii. @n ambele ca3uri se e1aluea3 e-presia #i dac ea este ade1rat 9deci diferit de 3ero< se e-ecut instruc+iune27. $ac e-presia este fals 9are 1aloarea 3ero< #i instruc+iunea if are #i parte de else atunci se e-ecut instruc+iune28. ,na #i numai una dintre cele dou instruc+iuni se e-ecut. $eoarece un if testea3 pur #i simplu 1aloarea numeric a unei e-presii* se admite o prescurtare #i anume4 if (expresie) n loc de4 if (expresie &" 0) $eoarece partea else a unei instruc+iuni if este op+ional* e-ist o ambiguitate cnd un else este omis dintr2o sec1en+ de if
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

B8

imbricat. 6ceasta se re3ol1 asociind else cu ultimul if care nu are else. Exemplu4 if (n>0) if (a>() : " a; else : " (; 0artea else apar+ine if2ului din interior. $ac nu dorim acest lucru atunci folosim acoladele pentru a for+a asocierea4 if (n>0) { if (a>() : " a; else : " (; ;nstruc+iunea condi+ional admite #i construc+ia else2if de forma4 if (expresie27) instruciune27 else if (expresie28) instruciune28 else if (expresie2?) instruc+iune2? else instruciune2A 6ceast sec1en+ de if se folose#te frec1ent n programe* ca mod de a e-prima o deci3ie multipl. K-presiile se e1aluea3 n ordinea n care apar; dac se ntlne#te o e-presie ade1rat* atunci se e-ecut instruc+iunea asociat cu ea #i astfel se termin ntregul lan+. Dricare instruc+iune poate fi o instruc+iune simpl sau un grup de instruc+iuni ntre acolade.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

B?

d ;nstruc+iunea dup ultimul else se e-ecut n ca3ul n care nici o e-presie nu a fost ade1rat. $ac n acest ca3 nu e-ist nici o ac+iune e-plicit de fcut* atunci partea else instruciune2A poate s lipseasc. Func+ia (inar9 din sec+iunea 7.B este un e-emplu de deci3ie multipl de ordinul ?. 0ot e-ista un numr arbitrar de construc+ii4 else if (expresie) instruciune grupate ntre un if ini+ial #i un else final. @ntotdeauna un else se leag cu ultimul if ntlnit.

+.'. Instruciunea while


Format4 while (expresie) instruciune ;nstruc+iunea se e-ecut repetat atta timp ct 1aloarea e-presiei este diferit de 3ero. /estul are loc naintea fiecrei e-ecu+ii a instruc+iunii. 0rin urmare ciclul este urmtorul4 se testea3 condi+ia din parante3e dac ea este ade1rat* deci e-presia din parante3e are o 1aloare diferit de 3ero* se e-ecut corpul instruc+iunii while* se 1erific din nou condi+ia* dac ea este ade1rat se e-ecut din nou corpul instruc+iunii. Cnd condi+ia de1ine fals* adic 1aloarea e-presiei din parante3e este 3ero* se face un salt la instruc+iunea de dup corpul instruc+iunii while* deci instruc+iunea while se termin.

+.). Instruciunea do
Format4 do instruciune while (expresie);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

BA

;nstruc+iunea se e-ecut repetat pn cnd 1aloarea e-presiei de1ine 3ero. /estul are loc dup fiecare e-ecu+ie a instruc+iunii.

+.+. Instruciunea for


Format4 for (expresie27<opt>; expresie28<opt>; expresie2?<opt>) instruciune 6ceast instruc+iune este ec"i1alent cu4 expresie27; while (expresie28) { instruciune; expresie2?; Expresie27 constituie ini+iali3area ciclului #i se e-ecut o singur dat naintea ciclului. Expresie28 specific testul care controlea3 ciclul. Kl se e-ecut naintea fiecrei itera+ii. $ac condi+ia din test este ade1rat atunci se e-ecut corpul ciclului* dup care se e-ecut expresie2?* care const de cele mai multe ori n modificarea 1alorii 1ariabilei de control al ciclului. :e re1ine apoi la ree1aluarea condi+iei. Ciclul se termin cnd condi+ia de1ine fals. Dricare dintre e-presiile instruc+iunii for sau c"iar toate pot lipsi. $ac lipse#te expresie28* aceasta implic faptul c clau3a while este ec"i1alent cu '"ile 97<* ceea ce nseamn o condi+ie totdeauna ade1rat. 6lte omisiuni de e-presii snt pur #i simplu eliminate din e-pandarea de mai sus. ;nstruc+iunile while #i for permit un lucru demn de obser1at #i anume* ele e-ecut testul de control la nceputul ciclului #i naintea intrrii n corpul instruc+iunii. $ac nu este nimic de fcut* nu se face nimic* cu riscul de a nu intra niciodat n corpul instruc+iunii.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

BB

+.4. Instruciunea switch


;nstruc+iunea switch este o deci3ie multipl special #i determin transferul controlului unei instruc+iuni sau unui bloc de instruc+iuni dintr2un #ir de instruc+iuni n func+ie de 1aloarea unei e-presii. Format4 switch (expresie) instruciune K-presia este supus la con1ersiile aritmetice obi#nuite dar re3ultatul e1alurii trebuie s fie de tip int. Fiecare instruc+iune din corpul instruc+iunii s'itc" poate fi etic"etat cu una sau mai multe prefi-e case astfel4 case expresie-constantP unde e-presie2constant trebuie s fie de tip int. 0oate e-ista de asemenea cel mult o instruc+iune etic"etat cu defaultP Cnd o instruc+iune switch se e-ecut* se e1aluea3 e-presia din parante3e #i 1aloarea ei se compar cu fiecare constant din fiecare case. $ac se gse#te o constant case egal cu 1aloarea e-presiei* atunci se e-ecut instruc+iunea care urmea3 dup case2ul respecti1. $ac nici o constant case nu este egal cu 1aloarea e-presiei #i dac e-ist un prefi- default* atunci se e-ecut instruc+iunea de dup el* altfel nici o instruc+iune din switch nu se e-ecut. 0refi-ele case #i default nu alterea3 flu-ul de control* care continu printre astfel de prefi-e. 0entru ie#irea din switch se folose#te instruc+iunea (rea, 91e3i sec+iunea E.G< sau return 91e3i sec+iunea E.70<. $e obicei instruc+iunea care constituie corpul unui switch este o instruc+iune compus. La nceputul acestei instruc+iuni pot aprea #i declara+ii* dar ini+iali3area 1ariabilelor automatice #i registru este inefecti1. na " n( " nc " 0; while (c"s)i%%*)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

BE

switch (c) { case !0!P case !'!P case !.!P case !0!P case !/!P case !1!P case !2!P case !R!P case !5!P case !4!P nc)c6!0!*%%; (rea,; case ! !P case !\r!P case !\t!P n(%%; (rea,; defaultP na%%; (rea,; printf("cifreP "); for (i"0; i<'0; i%%) printf(" #d",nc)i*); printf("\nspatii al(eP #d, alteleP #d\n", n(,na); @n acest e-emplu se parcurg toate caracterele dintr2un #ir* se numr cifrele* spa+iile albe #i alte caractere #i se afi#ea3 aceste numere nso+ite de comentarii. ;nstruc+iunea while este cea care asigur parcurgerea #irului pn la sfr#it. 0entru fiecare caracter se e-ecut corpul instruc+iunii while care const dintr2o singur instruc+iune switch. :e e1aluea3 e-presia ntreag din parante3e 9n ca3ul nostru caracterul c< #i se compar 1aloarea sa cu toate constantele2case. @n
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

B7

momentul cnd a1em egalitate se ncepe e-ecu+ia de la case2ul respecti1. 6fi#area re3ultatelor se face prin intermediul instruc+iunii for #i a func+iei printf 91e3i capitolul 77<.

+.5. Instruciunea break


Format4 (rea,; 6ceast instruc+iune determin terminarea celei mai interioare instruc+iuni while* do* for sau switch care o con+ine. Controlul trece la instruc+iunea care urmea3 dup instruc+iunea astfel terminat.

+.6. Instruciunea continue


Format4 continue; 6ceast instruc+iune determin trecerea controlului la por+iunea de continuare a ciclului celei mai interioare instruc+iuni while* do sau for care o con+ine* adic la sfr#itul ciclului #i reluarea urmtoarei itera+ii a ciclului. @n while #i do se continu cu testul* iar n for se continu cu expresie-?. %ai precis n fiecare dintre instruc+iunile4 while (...) { ... continP; for (...) { ... continP; do { ... continP; while (...);

dac apare o instruc+iune continue aceasta este ec"i1alent cu un salt la etic"eta contin. $up continP urmea3 o instruc+iune 1id 91e3i sec+iunea E.77<. 0or+iunea de program din e-emplul urmtor prelucrea3 numai elementele po3iti1e ale unui masi1.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

BG

for (i"0; i<n; i%%) { if (a)i*<0) =W sare peste elementele negati1e W= continue; ... =W prelucrea3 elementele po3iti1e W=

+.17. Instruciunea return


D instruc+iune return permite ie#irea dintr2o func+ie #i transmiterea controlului apelantului func+iei. D func+ie poate returna 1alori apelantului su* prin intermediul unei instruc+iuni return. Formate4 return; return expresie; @n primul ca3 1aloarea returnat nu este definit. @n al doilea ca3 1aloarea e-presiei este returnat apelantului func+iei. $ac se cere* e-presia este con1ertit* ca ntr2o atribuire* la tipul func+iei n care ea apare.

+.11. Instruciunea $id


Format4 ; ;nstruc+iunea 1id este util pentru a introduce o etic"et naintea unei acolade drepte* ntr2o instruc+iune compus* sau pentru a introduce un corp nul ntr2o instruc+iune de ciclare care cere corp al instruc+iunii* ca de e-emplu while sau for. Exemplu4 for (nc"0; s)nc*&"0; %%nc) ; 6ceast instruc+iune numr caracterele unui #ir. Corpul lui for este 1id* deoarece tot lucrul se face n partea de test #i actuali3are dar sinta-a lui for cere un corp al instruc+iunii. ;nstruc+iunea 1id satisface acest lucru.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

BH

4. 9unciile i structura unui program


Func+iile snt elementele de ba3 ale unui program scris n C; orice program* de orice dimensiune* const din una sau mai multe func+ii* care specific opera+iile care trebuie efectuate. D func+ie ofer un mod con1enabil de ncapsulare a anumitor calcule ntr2o cutie neagr care poate fi utili3at apoi fr a a1ea grija con+inutului ei. Func+iile snt ntr2ade1r singurul mod de a face fa+ comple-it+ii programelor mari. Func+iile permit desfacerea programelor mari n unele mici #i dau utili3atorului posibilitatea de a de31olta programe* folosind ceea ce al+ii au fcut deja n loc s o ia de la nceput. Limbajul C a fost conceput s permit definirea de func+ii eficiente #i u#or de mnuit. @n general e bine s concepem programe constituite din mai multe func+ii mici dect din pu+ine func+ii de dimensiuni mari. ,n program poate fi mpr+it n mai multe fi#iere surs n mod con1enabil* iar fi#ierele surs pot fi compilate separat. %ai precis* un program C const dintr2o sec1en+ de defini+ii e-terne. 6cestea snt defini+ii de func+ii #i de date. :inta-a defini+iilor e-terne este aceea#i ca #i a tuturor declara+iilor.

4.1. 8e#iniia #unciilor


:inta-a defini+iei unei func+ii este urmtoarea4 (efiniia-funciei4 tip-funcie<opt> nume-funcie(lista-parametri) corp-funcie !ista-parametri4 declaraie-parametru declaraie-parametru, lista-parametri *orpul-funciei4 instruciune-compus $intre specificatorii de clas de memorie numai e8tern #i static snt admi#i. ,n declarator de func+ie este similar cu un
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

E0

declarator pentru funcie care returneaz """ cu e-cep+ia c el listea3 parametrii formali ai func+iei care se define#te. $up cum se obser1* diferitele pr+i pot s lipseasc; o func+ie minim este4 dumm9() { func+ia care nu face nimic. 6ceast func+ie poate fi util n programe* +innd locul unei alte func+ii n de31oltarea ulterioar a programului. &umele func+iei poate fi precedat de un tip* dac func+ia returnea3 altce1a dect o 1aloare ntreag 91e3i sec+iunea 7.8<. &umele func+iei poate fi de asemenea precedat de clasa de memorie e8tern sau static. $ac nici un specificator de clas de memorie nu este pre3ent* atunci func+ia este automat declarat e-tern* deoarece n C nu se admite ca o func+ie s fie definit n interiorul altei func+ii. $eclara+ia unei func+ii se face implicit la apari+ia ei. :e interpretea3 ca func+ie orice identificator nedeclarat anterior #i urmat de o parante3 a(a. 0entru a e1ita surpri3e neplcute datorit neconcordan+ei dintre tipurile de parametri aceast practic nu este recomandat. $m mai jos un e-emplu de func+ie complet definit4 int ma8(int a, int (, int c) { int m; m " (a>() O a P (; return (m>c) O m P c; 6ceast func+ie determin ma-imul dintre ? numere date4 int este un specificator de tip care indic faptul c func+ia mareturnea3 o 1aloare ntreag; ma8(int a, int (, int c) este declara+ia func+iei #i a parametrilor formali; { . . . este corpul func+iei. : ilustrm mecanismul definirii unei func+ii scriind func+ia putere power(m,n) care ridic un ntreg m la o putere ntreag po3iti1 n. 6stfel 1aloarea lui power(.,1) este ?8. 6ceast func+ie
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

E7

desigur nu este complet* deoarece calculea3 numai puteri po3iti1e de ntregi mici. 0re3entm mai jos func+ia power #i un program principal care o apelea3* pentru a putea 1edea #i structura unui program. power(int 8, int n) { int i, p; p " '; for (i"'; i<"n; %%i) p " p + 8; return p; main() { int i; for (i"0; i<'0; %%i) printf(" #d #d\n", i, power(.,i), power(60,i)); Func+ia power este apelat n programul principal de dou ori. Fiecare apel transmite func+iei dou argumente. Re3ultatul este afi#at de func+ia de bibliotec printf 91e3i capitolul 77<. &umele func+iei este urmat obligatoriu de parante3e* c"iar dac lista parametrilor este 1id. @n general numele func+iei este ales dup dorin+a utili3atorului. /otu#i n fiecare program trebuie s e-iste o func+ie cu numele impus main; orice program #i ncepe e-ecu+ia cu func+ia main. Celelalte func+ii snt apelate din interiorul func+iei main. ,nele dintre func+iile apelate snt definite n acela#i program* altele snt con+inute ntr2o bibliotec de func+ii. Comunicarea ntre func+ii se face prin argumente #i 1alori returnate de func+ii. Comunicarea ntre func+ii poate fi fcut #i prin intermediul 1ariabilelor e-terne. D func+ie poate fi declarat #i static. @n acest ca3 ea poate fi apelat numai din fi#ierul unde a fost definit.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

E8

Func+iile n C pot fi folosite recursi1* deci o func+ie se poate apela pe ea ns#i fie direct* fie indirect. @n general ns recursi1itatea nu face economie de memorie* deoarece trebuie men+inut o sti1 cu 1alorile de prelucrat.

4.2. :pelul #unciilor


@n limbajul C orice func+ie este apelat prin numele ei* urmat de lista real a argumentelor* nc"is ntre parante3e. $ac ntr2o e-presie numele func+iei nu este urmat imediat de o parante3 a(a* adic func+ia nu apare pe po3i+ia de apel de func+ie atunci nu se reali3ea3 imediat apelul func+iei respecti1e ci se generea3 un pointer la func+ie 91e3i sec+iunea H.77<.

4.3. ;e$enirea din #uncii


Re1enirea dintr2o func+ie se face prin intermediul unei instruc+iuni return. Caloarea pe care o func+ie o calculea3 poate fi returnat prin instruc+iunea return* care dup cum am 13ut are dou formate4 return; return expresie; Ca argument poate aprea orice e-presie admis n C. Func+ia returnea3 1aloarea acestei e-presii func+iei apelante. D func+ie nu returnea3 n mod obligatoriu o 1aloare. D instruc+iune return* fr e-presie ca parametru* cau3ea3 numai transferul controlului func+iei apelante nu #i o 1aloare util. La rndul su func+ia apelant poate ignora 1aloarea returnat. $e obicei o func+ie returnea3 o 1aloare de tip ntreg. $ac se dore#te ca func+ia s returne3e un alt tip* atunci numele tipului trebuie s precead numele func+iei* iar programul trebuie s con+in o declara+ie a acestei func+ii att n fi#ierul n care func+ia este definit ct #i n fi#ierul unde func+ia este apelat.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

E?

0entru a e1ita orice confu3ie se recomand ca tipul 1alorii returnate de func+ie s fie ntotdeauna preci3at* iar dac dorim n mod e-pres ca func+ia s nu returne3e o 1aloare s folosim tipul -oid. $e e-emplu* func+ia atof(s) din biblioteca asociat compilatorului con1erte#te #irul s de cifre n 1aloarea sa n dubl preci3ie. Com declara func+ia sub forma4 dou(le atof(char s)*); sau mpreun cu alte 1ariabile de tip dou(le4 dou(le sum, atof(char s)*); Func+iile nu pot returna masi1e* structuri* reuniuni sau func+ii. $ac o func+ie returnea3 o 1aloare de tip char* nu este ne1oie de nici o declara+ie de tip din cau3a con1ersiilor implicite. /otdeauna tipul char este con1ertit la int n e-presii.

4.'. :rgumentele #unciei i transmiterea parametrilor


D metod de a comunica datele ntre func+ii este prin argumente. 0arante3ele mici care urmea3 dup numele func+iei nc"id lista argumentelor. @n limbajul C argumentele func+iilor snt transmise prin 1aloare. 6ceasta nseamn c n C func+ia apelat prime#te 1alorile argumentelor sale ntr2o copie particular de 1ariabile temporare 9n realitate pe sti1<. Func+ia apelat nu poate altera dect 1ariabilele sale particulare* adic copiile temporare. 6pelul prin 1aloare este o posibilitate* dar nu #i o obligati1itate. 6pelul prin 1aloare conduce la programe mai compacte cu mai pu+ine 1ariabile e-terne* deoarece argumentele pot fi tratate ca 1ariabile locale* #i care pot fi modificate con1enabil n rutina apelat. Ca e-emplu* pre3entm o 1ersiune a func+iei putere care face u3 de acest fapt4 power(int 8, int n) { int p;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

EA

for (p"'; n>0; 66n) p " p + 8; return p; 6rgumentul n este utili3at ca o 1ariabil temporar #i este decrementat pn de1ine 3ero; astfel nu este ne1oie de nc o 1ariabil i. Drice opera+ii s2ar face asupra lui n n interiorul func+iei* ele nu au efect asupra argumentului pentru care func+ia a fost apelat. $ac totu#i se dore#te alterarea efecti1 a unui argument al func+iei apelante* acest lucru se reali3ea3 cu ajutorul pointerilor sau a 1ariabilelor declarate e-terne. @n ca3ul pointerilor* func+ia apelant trebuie s furni3e3e adresa 1ariabilei de modificat 9te"nic printr2un pointer la aceast 1ariabil<* iar func+ia apelat trebuie s declare argumentul corespun3tor ca fiind un pointer. Referirea la 1ariabila de modificat se face prin adresare indirect 91e3i capitolul H<. 0rintre argumentele func+iei pot aprea #i nume de masi1e. @n acest ca3 1aloarea transmis func+iei este n realitate adresa de nceput a masi1ului 9elementele masi1ului nu snt copiate<. 0rin inde-area acestei 1alori func+ia poate a1ea acces #i poate modifica orice element din masi1.

4.). 9uncii cu numr $ariabil de parametri


0entru func+iile cu numr 1ariabil de parametri standardul 6&:; define#te o construc+ie special ... * numit elips. 6cesta este de e-emplu ca3ul func+iilor de citire #i scriere cu format 9familiile ...scanf #i ...printf 2 a se 1edea capitolul 77<. @n acest ca3* parametrii fic#i snt 1erifica+i la compilare* iar cei 1ariabili snt transmi#i ca #i cnd nu ar e-ista prototip de func+ie. 0entru simplitatea e-punerii am pstrat con1en+iile definite de standardele mai 1ec"i ale limbajului* pstrate #i de standardul 6&:; C. D func+ie poate fi declarat fr nici un parametru* compilatorul deducnd de aici c func+ia respecti1 poate a1ea oric+i parametri de orice tip. &u se recomand totu#i o asemenea practic deoarece este
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

EB

posibil s se cree3e confu3ii care conduc la erori n e-ecu+ia programelor* erori care se corectea3 foarte greu n ca3ul programelor mari.

4.+. 3"emple de #uncii i programe


7. 6cest e-emplu este un program de cutare #i imprimare a tuturor liniilor dintr2un te-t care con+in o anumit configura+ie de caractere* de e-emplu cu1ntul engle3esc "the". :tructura de ba3 a acestui program este4 while (mai e-ist linii surs) if (linia con+ine configura+ia de caractere) imprim linia @n scopul scrierii acestui program 1om scrie trei func+ii. Func+ia 7etline cite#te o linie din te-tul surs #i returnea3 lungimea ei. 6ceast func+ie are dou argumente. 6rgumentul s indic numele masi1ului unde se 1a citi linia* iar argumentul lim repre3int lungimea ma-im a unei linii care poate fi citit. Func+ia inde8 caut configura+ia de caractere dorit n interiorul liniei #i furni3ea3 po3i+ia sau inde-ul n #irul s* unde ncepe #irul t* sau 7 dac linia nu con+ine #irul t. 6rgumentele func+iei snt s care repre3int adresa #irului de studiat #i t care repre3int configura+ia cutat. Func+ia care reali3ea3 afi#area este printf din bibliotec. 0rogramul care reali3ea3 structura de mai sus este4 #define B<;>JA@ '000 #define @S= 6' 7etline(char s)*, int lim) { =W cite#te o linie n s; returnea3 lungimea W= int c, i; i " 0; while (66lim>0 $$ (c"7etchar())&" @S= $$ c&"!\n!)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

EE

s)i%%*"c; if (c""!\n!) s)i%%*"c; s)i*"!\0!; return i; inde8(char s)*, char t)*) { =W returnea3 po3i+ia din #irul s unde ncepe #irul t* sau 7 W= int i,G,,; for (i"0; s)i*&"!\0!; i%%) { for (G"i, ,"0; t),*&"!\0! $$ s)G*""t),*; G%%, ,%%) ; if (t),*""!\0!) return i; return 6'; main() { =W imprim toate liniile care con+in cu1ntul the W= char line )B<;>JA@*; while (7etline(line, B<;>JA@)>0) if (inde8(line,"the")>"0) printf("#s",line); 8. Func+ia atof con1erte#te un #ir de cifre din formatul 6:C;; ntr2un numr flotant n preci3ie dubl. dou(le atof(char s)*) { =W con1erte#te #irul s n dubl preci3ie W= dou(le -al, power; int i, si7n; for (i"0; s)i*""! ! HH s)i*""!\n! HH
s)i*""!\t!; i%%) ; E7 =W sare peste spa+ii albe W=
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

si7n " '; if (s)i*""!%! HH s)i*""!6!) si7n " (s)i%%*""!%!) O ' P 6'; for (-al"0; s)i*>"!0! $$ s)i*<"!4!; i%%) -al " '0 + -al % s)i* 6 !0!; if (s)i*"" !.!) =W punct 3ecimal W= i%%; for (power"'; s)i*>"!0! $$ s)i*<"!4!; i%%) { -al " '0 + -al %s)i* 6 !0!P power +" '0; return si7n + -al F power; ?. Func+ia atoi con1erte#te un #ir de cifre n ec"i1alentul lor numeric ntreg. atoi(char s)*) { =W con1erte#te #irul s la un ntreg W= int i,n; n " 0; for (i"0; s)i*>"!0! $$ s)i*<"!4!; i%%) n " '0 + n %s)i* 6 !0!; return n; A. Func+ia lower con1erte#te literele mari din setul de caractere 6:C;; n litere mici. $ac lo'er prime#te un caracter care nu este o liter mare atunci l returnea3 nesc"imbat. lower(int c) { if (c>"!<! $$ c<"!T!) return c % !a! 6 !<!; else return c;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

EG

B. Func+ia (inar9 reali3ea3 cutarea 1alorii 8 ntr2un masi1 sortat -* care are n elemente. (inar9(int 8, int -)*, int n) { =W caut 8 n -0* -'* ...* -n6' W= int low, hi7h, mid; low " 0; hi7h " n 6 '; while (low<"hi7h) { mid " (low % hi7h) F .; if (8 < -)mid*) hi7h " mid 6 '; else if (8 > -)mid*) low " mid % '; else =W s2a gsit o intrare W= return(mid); return 6'; Func+ia returnea3 po3i+ia lui 8 9un numr ntre 0 #i n7<* dac 8 apare n - sau 7 altfel. K-emplul ilustrea3 o deci3ie tripl* dac 8 este mai mic* mai mare sau egal cu elementul din mijlocul #irului -)mid*.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

EH

5. <iniile de control ale compilatorului


Limbajul C ofer o facilitate de e-tensie a limbajului cu ajutorul unui preprocesor de macro2opera+ii simple. Folosirea liniilor de forma4 #define #include este cea mai u3ual metod pentru e-tensia limbajului* caracterul a #a 9die3< indicnd faptul c aceste linii 1or fi tratate de ctre preprocesor. Liniile precedate de caracterul a #a au o sinta- independent de restul limbajului #i pot aprea oriunde n fi#ierul surs* a1nd efect de la punctul de defini+ie pn la sfr#itul fi#ierului.

5.l. 2nlocuirea simbolurilor= substituii macro


D defini+ie de forma4 #define identificator ir-simboluri determin ca preprocesorul s nlocuiasc toate apari+iile ulterioare ale identificatorului cu ir-simboluri dat 9ir-simboluri nu se termin cu a;a deoarece n urma substitu+iei identificatorului cu acest #ir ar aprea prea multe caractere a;a<. $ir-simboluri sau te-tul de nlocuire este arbitrar. @n mod normal el este tot restul liniei ce urmea3 dup identificator. D defini+ie ns poate fi continuat pe mai multe linii* introducnd ca ultim caracter n linia de continuat caracterul a\a 9bacIslas"<. ,n identificator care este subiectul unei linii #define poate fi redefinit ulterior n program printr2o alt linie #define. @n acest ca3* prima defini+ie are efect numai pn la defini+ia urmtoare. :ubstitu+iile nu se reali3ea3 n ca3ul n care identificatorii snt ncadra+i ntre g"ilimele. $e e-emplu fie defini+ia4 #define <>=< ' Driunde 1a aprea n programul surs identificatorul 6LF6 el 1a fi nlocuit cu constanta 7* cu e-cep+ia unei situa+ii de forma4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70

printf("<>=<"); n care se 1a tipri c"iar te-tul 6LF6 #i nu constanta 7* deoarece identificatorul este ncadrat ntre g"ilimele. 6ceast facilitate este deosebit de 1aloroas pentru definirea constantelor simbolice ca n4 #define R<CMJT@ '00 int ta()R<CMJT@*; deoarece ntr2o e1entual modificare a dimensiunii tabelului ta( se 1a modifica doar o singur linie n fi#ierul surs. D linie de forma4 #define identif(identif27*...* identif2n) ir-simboluri n care nu e-ist spa+iu ntre primul identificator #i caracterul a (a este o defini+ie pentru o macro2opera+ie cu argumente* n care te-tul de nlocuire 9ir-simboluri< depinde de modul n care se apelea3 macro2 ul respecti1. Ca un e-emplu s definim o macro2opera+ie numit ma8 n felul urmtor4 #define ma8(a,() ((a)>(() O (a) P (()) atunci linia dintr2un program surs4 8 " ma8(p%I,r%s); 1a fi nlocuit cu4 8 " ((p%I)>(r%s) O (p%I) P (r%s)); 6ceast macro2defini+ie furni3ea3 o funcie maximum care se e-pandea3 n cod* n loc s se reali3e3e un apel de func+ie. 6cest macro 1a ser1i pentru orice tip de date* nefiind ne1oie de diferite tipuri de func+ii ma-imum pentru diferite tipuri de date* a#a cum este necesar n ca3ul func+iilor propriu23ise. $ac se e-aminea3 atent e-pandarea lui ma8 se pot obser1a anumite probleme ce pot genera erori* #i anume4 e-presiile fiind e1aluate de dou ori* n ca3ul n care ele con+in opera+ii ce generea3 efecte colaterale 9apelurile de func+ii* operatorii de incrementare< se pot ob+ine re3ultate total eronate. $e asemenea* trebuie a1ut mare grij la folosirea parante3elor pentru a face sigur ordinea e1alurii dorite. $e e-emplu macro2 opera+ia sIuare(8) definit prin4 #define sIuare(8) 8+8 care se apelea3 n programul surs sub forma4 : " sIuare(:%');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77

1a produce un re3ultat* altul dect cel scontat* datorit priorit+ii mai mari a operatorului + fa+ de cea a operatorului %.

5.2. Includerea #iierelor


D linie de forma4 #include "nume-fiier" reali3ea3 nlocuirea liniei respecti1e cu ntregul con+inut al fi#ierului nume2fi#ier. Fi#ierul denumit este cutat n primul rnd n directorul fi#ierului surs curent #i apoi ntr2o succesiune de locuri standard* cum ar fi biblioteca ; +D standard asociat compilatorului. 6lternati1* o linie de forma4 #include <nume-fiier> caut fi#ierul nume2fi#ier numai n biblioteca standard #i nu n directorul fi#ierului surs. $eseori* o linie sau mai multe linii* de una sau ambele forme apar la nceputul fiecrui fi#ier surs pentru a include defini+ii comune 9prin declara+ii #define #i declara+ii e-terne pentru 1ariabilele globale<. Facilitatea de includere a unor fi#iere ntr2un te-t surs este deosebit de util pentru gruparea declara+iilor unui program mare. Ka 1a asigura faptul c toate fi#ierele surs 1or primi acelea#i defini+ii #i declara+ii de 1ariabile* n felul acesta eliminndu2se un tip particular de erori. $ac se modific un fi#ier inclus printr2o linie #include* toate fi#ierele care depind de el trebuie recompilate.

5.3. Compilarea condiionat


D linie de control a compilatorului de forma4 #if expresie-constant 1erific dac e-presia constant este e1aluat la o 1aloare diferit de 3ero. D linie de control de forma4 #ifdef identificator
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78

1erific dac identificatorul a fost subiectul unei linii de control de forma #define. D linie de control de forma4 #ifndef identificator 1erific dac identificatorul este nedefinit n preprocesor. /oate cele trei forme de linii de control precedente pot fi urmate de un numr arbitrar de linii care* e1entual* pot s con+in o linie de control forma4 #else #i apoi de o linie de control de forma4 #endif $ac condi+ia supus 1erificrii este ade1rat* atunci orice linie ntre #else #i #endif este ignorat. $ac condi+ia este fals atunci toate liniile ntre testul de 1erificare #i un #else sau n lipsa unui #else pn la #endif snt ignorate. /oate aceste construc+ii pot fi imbricate.

5.'. !tili1area dircti$elor de compilare


0re3entm n continuare un e-emplu didactic de utili3are a directi1elor de compilare n de31oltarea unor proiecte. :e cite#te de la tastatur o perec"e de numere naturale p #i I. : se determine dac fiecare din cele dou numere este prim sau nu* #i s se calcule3e cel mai mare di1i3or comun. : re3ol1m aceast problem folosind dou fi#iere surs. 0rimul con+ine func+ia main #i apelea3 dou func+ii4 eprim #i cmmdc. 6l doilea fi+ier implementea3 cele dou func+ii. 0re3entm mai nti un fi#ier "eader 9 numere.h< care con+ine defini+iile celor dou func+ii. #ifndef UAumereUH #define UAumereUH unsi7ned eprim(unsi7ned n); unsi7ned cmmdc(unsi7ned p, unsi7ned I); #endif Fi#ierul surs princ.c este foarte scurt.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?

#include <stdio.h> #include "numere.h" static -oid citire(unsi7ned +n) { scanf("#u",n); if (eprim(+n)) printf("#u e prim\n",+n); else printf("#u nu e prim\n",+n); int main() { unsi7ned p,I,,; citire($p); citire($I); ,"cmmdc(p,I); printf("DmmdcP #u\n",,); return 0; Fi#ierul surs numere.c este pre3entat n continuare. #include "numere.h" unsi7ned eprim(unsi7ned n) { unsi7ned i,a,r; if (n""0) return 0; if (n</) return '; if ((n$')""0) return 0; for (i"0; ; i%".) { r"n#i; if (r""0) return 0; a"nFi; if (a<"i) return '; unsi7ned cmmdc(unsi7ned p, unsi7ned I) { while ((p>0) $$ (I>0)) if (p>I) p#"I; else I#"p;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A

if (p""0) return I; else return p; 0entru a ob+ine un program e-ecutabil din aceste dou fi#iere se poate utili3a o singur comand de compilare4 *c princ.c numere.c opiuni2de2compilare unde *c este numele compilatorului folosit 9e-emplu4 (cc* 7cc<. Dp+iunile de compilare 9atunci cnd snt necesare< snt specifice mediului de programare folosit. 0roiectele 5 programe de dimensiuni mari 5 snt compuse de cele mai multe ori din module care se elaborea3 #i se pun la punct separat. ,neori pot fi identificate func+ii care pre3int un interes general mai mare* #i care pot fi utili3ate n elaborarea unor tipuri de aplica+ii foarte di1erse. 6cestea snt de31oltate separat #i* dup ce au fost puse la punct n totalitate* se depun ntr2o bibliotec de func+ii n format obiect. @n momentul n care acestea snt incluse n proiecte nu se mai pierde timp cu compilarea modulelor surs. @n sc"imb modulele care le apelea3 au ne1oie de modul cum snt descrise aceste func+ii* #i acesta se pstrea3 n fi#iere "eader.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7B

6. Pointeri i masi$e
,n pointer este o 1ariabil care con+ine adresa unei alte 1ariabile. 0ointerii snt foarte mult utili3a+i n programe scrise n C* pe de o parte pentru c uneori snt unicul mijloc de a e-prima un calcul* iar pe de alt parte pentru c ofer posibilitatea scrierii unui program mai compact #i mai eficient dect ar putea fi ob+inut prin alte ci.

6.1. Pointeri i adrese


$eoarece un pointer con+ine adresa unui obiect* cu ajutorul lui putem a1ea acces* n mod indirect* la acea 1ariabil 9obiect<. : presupunem c 8 este o 1ariabil de tip ntreg #i p8 un pointer la aceast 1ariabil. 6tunci aplicnd operatorul unar $ lui 8* instruc+iunea4 p8 " $8; atribuie 1ariabilei p8 adresa 1ariabilei 8; n acest fel spunem c p8 indic 9pointea3< spre 8. ;n1ers* dac p8 con+ine adresa 1ariabilei 8* atunci instruc+iunea4 9 " +p8; atribuie 1ariabilei 9 con+inutul loca+iei pe care o indic p8. K1ident toate 1ariabilele care snt implicate n aceste instruc+iuni trebuie declarate. 6ceste declara+ii snt4 int 8,9; int +p8; $eclara+iile 1ariabilelor 8 #i 9 snt deja cunoscute. $eclara+ia pointerului p8 este o noutate. 6 doua declara+ie indic faptul c o combina+ie de forma +p8 este un ntreg* iar 1ariabila p- care apare n conte-tul +p8 este ec"i1alent cu un pointer la o 1ariabil de tip ntreg. @n locul tipului ntreg poate aprea oricare dintre tipurile admise n limbaj #i se refer la obiectele pe care le indic p8.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E

0ointerii pot aprea #i n e-presii* ca de e-emplu n e-presia urmtoare4 9 " +p8 % '; unde 1ariabilei 9 i se atribuie con+inutul 1ariabilei 8 plus '. ;nstruc+iunea4 d " sIrt((dou(le)+p8); are ca efect con1ertirea con+inutului 1ariabilei 8 pe care o indic p8 n tip dou(le #i apoi depunerea rdcinii ptrate a 1alorii astfel con1ertite n 1ariabila d. Referiri la pointeri pot aprea de asemenea #i n partea stng a atribuirilor. $ac* de e-emplu* p8 indic spre 8* atunci4 +p8 " 0; atribuie 1ariabilei 8 1aloarea 3ero* iar4 +p8 %" '; incrementea3 con+inutul 1ariabilei 8 cu '* ca #i n e-presia4 (+p8)%%; @n acest ultim e-emplu parante3ele snt obligatorii deoarece* n lipsa lor* e-presia ar incrementa pe p8 n loc de con+inutul 1ariabilei pe care o indic 9operatorii unari +* %% au aceea#i preceden+ #i snt e1alua+i de la dreapta spre stnga<.

6.2 Pointeri i argumente de #uncii


$eoarece n limbajul C transmiterea argumentelor la func+ii se face prin 1aloare 9#i nu prin referin+<* func+ia apelat nu are posibilitatea de a altera o 1ariabil din func+ia apelant. 0roblema care se pune este cum procedm dac totu#i dorim s sc"imbm un argumentX $e e-emplu* o rutin de sortare poate sc"imba ntre ele dou elemente care nu respect ordinea dorit* cu ajutorul unei func+ii swap. Fie func+ia swap definit astfel4 swap(int 8, int 9) { int temp; temp " 8; 8 " 9;
77

=W gre#it W=

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

9 " temp; Func+ia swap apelat prin swap(a,() nu 1a reali3a ac+iunea dorit deoarece ea nu poate afecta argumentele a #i ( din rutina apelant. K-ist ns o posibilitate de a ob+ine efectul dorit* dac func+ia apelant transmite ca argumente pointeri la 1alorile ce se doresc intersc"imbate. 6tunci n func+ia apelant apelul 1a fi4 swap($a,$(); iar forma corect a lui swap este4 swap(int +p8, int +p9) {=W intersc"imb Wp- #i Wp) W= int temp; temp " +p8; +p8 " +p9; +p9 " temp;

6.3. Pointeri i masi$e


@n limbajul C e-ist o strns legtur ntre pointeri #i masi1e. Drice opera+ie care poate fi reali3at prin indicarea masi1ului poate fi de asemenea fcut prin pointeri* care* n plus* conduce #i la o accelerare a opera+iei. $eclara+ia4 int a)'0*; define#te un masi1 de dimensiune 70* care repre3int un bloc de 70 obiecte consecuti1e numite a)0** ... a)4*. &ota+ia a)i* repre3int al i2lea element al masi1ului sau elementul din po3i+ia i+'* ncepnd cu primul element. $ac pa este un pointer la un ntreg declarat sub forma4 int +pa; atunci atribuirea4 pa " $a)0*; ncarc 1ariabila pa cu adresa primului element al masi1ului a. 6tribuirea4 8 " +pa;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7G

copia3 con+inutul lui a)0* n 8. $ac pa indic un element particular al unui masi1 a* atunci prin defini+ie pa%i indic un element cu i po3i+ii dup elementul pe care l indic pa* dup cum pa6i indic un element cu i po3i+ii nainte de cel pe care indic pa. 6stfel* dac 1ariabila pa indic pe a)0* atunci +(pa%i) se refer la con+inutul lui a)i*. 6ceste obser1a+ii snt ade1rate indiferent de tipul 1ariabilelor din masi1ul a. @ntreaga aritmetic cu pointeri are n 1edere faptul c e-presia pa%i nseamn de fapt nmul+irea lui i cu lungimea elementului pe care l indic pa #i adunarea apoi la pa* ob+inndu2se astfel adresa elementului de indice i al masi1ului. Coresponden+a dintre inde-area ntr2un masi1 #i aritmetica de pointeri este foarte strns. $e fapt* o referire la un masi1 este con1ertit de compilator ntr2un pointer la nceputul masi1ului. Kfectul este c un nume de masi1 este o e-presie pointer* deoarece numele unui masi1 este identic cu numele elementului de indice 3ero din masi1. 6tribuirea4 pa " $a)0*; este identic cu4 pa " a; $e asemenea* e-presiile a)i* #i +(a%i) snt identice. 6plicnd operatorul V la ambele pr+i ob+inem $a)i* identic cu a%i. 0e de alt parte* dac pa este un pointer* e-presiile pot folosi acest pointer ca un indice4 pa)i* este identic cu +(pa%i). 0e scurt orice e-presie de masi1 #i indice poate fi scris ca un pointer #i un deplasament #i in1ers* c"iar n aceea#i instruc+iune. K-ist ns o singur diferen+ ntre un nume de masi1 #i un pointer la nceputul masi1ului. ,n pointer este o 1ariabil* deci pa " a #i pa%% snt instruc+iuni corecte. $ar un nume de masi1 este o constant #i deci construc+ii de forma a " pa* a%% sau p " $a snt ilegale. Cnd se transmite unei func+ii un nume de masi1* ceea ce se transmite de fapt este adresa primului element al masi1ului. 6#adar*
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7H

un nume de masi1* argument al unei func+ii* este n realitate un pointer* adic o 1ariabil care con+ine o adres. Fie de e-emplu func+ia strlen care calculea3 lungimea #irului s4 strlen(char +s) { =W returnea3 lungimea #irului W= int n; for (n"0; +s&"!\0!; s%%) n%%; return n; ;ncrementarea lui s este legal deoarece s este o 1ariabil pointer. s%% nu afectea3 #irul de caractere din func+ia care apelea3 pe strlen* ci numai copia adresei #irului din func+ia strlen. Kste posibil s se transmit unei func+ii* ca argument* numai o parte a unui masi1* printr2un pointer la nceputul sub2masi1ului respecti1. $e e-emplu* dac a este un masi1* atunci4 f($a).*) f(a%.) transmit func+iei f adresa elementului a).** deoarece $a).* #i a%. snt e-presii pointer care* ambele* se refer la al treilea element al masi1ului a. @n cadrul func+iei f argumentul se poate declara astfel4 f(int arr)*) { sau f(int +arr) { $eclara+iile int arr)* #i int +arr snt ec"i1alente* op+iunea pentru una din aceste forme depin3nd de modul n care 1or fi scrise e-presiile n interiorul func+iei.

6.'. :ritmetica de adrese


$ac p este un pointer* atunci p %" i incrementea3 pe p pentru a indica cu i elemente dup elementul pe care l indic n prealabil p. 6ceast construc+ie #i altele similare snt cele mai simple #i comune formule ale aritmeticii de adrese* care constituie o
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

G0

caracteristic puternic a limbajului C. : ilustrm cte1a din propriet+ile aritmeticii de adrese scriind un alocator rudimentar de memorie. Fie rutina alloc(n) care returnea3 un pointer p la o 3on de n caractere consecuti1e care 1or fi folosite de rutina apelant pentru memorarea unui #ir de caractere. Fie rutina free(p) care eliberea3 o 3on ncepnd cu adresa indicat de pointerul p pentru a putea fi refolosit mai tr3iu. Qona de memorie folosit de rutinele alloc #i free este o sti1 func+ionnd pe principiul ultimul intrat primul ie#it* iar apelul la free trebuie fcut n ordine in1ers cu apelul la alloc. : considerm c func+ia alloc 1a gestiona sti1a ca pe elementele unui masi1 pe care l 1om numi alloc(uf. Com mai folosi un pointer la urmtorul element liber din masi1* pe care2l 1om numi allocp. Cnd se apelea3 rutina alloc pentru n caractere* se 1erific dac e-ist suficient spa+iu liber n masi1ul alloc(uf. $ac da* alloc 1a returna 1aloarea curent a lui allocp* adic adresa de nceput a blocului cerut* dup care 1a incrementa pe allocp cu n pentru a indica urmtoarea 3on liber. free(p) actuali3ea3 allocp cu 1aloarea p* dac p indic n interiorul lui alloc(uf. #define A?>> 0 =W 1aloarea pointerului pentru semnali3area erorii W= #define <>>SDMJT@ '000 =W dimensiunea spa+iului disponibil W= static char alloc(uf )<>>SDMJT@*; =W memoria pentru alloc W= static char +allocp " alloc(uf; =W urmtoarea po3i+ie liber W= char +alloc(int n) { =W returnea3 pointer la n caractere W= if (allocp%n<"alloc(uf%<>>SDMJT@) { allocp %" n; =W dimensiunea satisfcut W= return allocp6n; =W 1ec"ea 1aloare W= else
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

G7

return A?>>;

=W nu este spa+iu suficient W=

free(char +p) { =W eliberea3 memoria indicat de p W= if (p>"alloc(uf $$ p<alloc(uf%<>>SDMJT@) allocp " p; /estul if (allocp%n<"alloc(uf%<>>SDMJT@) 1erific dac e-ist spa+iu suficient pentru satisfacerea cererii de alocare a n caractere. $ac cererea poate fi satisfcut* alloc re1ine cu un pointer la 3ona de n caractere consecuti1e. $ac nu* alloc trebuie s semnale3e lipsa de spa+iu pe care o face returnnd 1aloarea constantei simbolice A?>>. Limbajul C garantea3 c nici un pointer care indic corect o dat nu 1a con+ine 3ero* prin urmare o re1enire cu 1aloarea 3ero poate fi folosit pentru semnalarea unui e1eniment anormal 9n ca3ul nostru* lipsa de spa+iu<. 6tribuirea 1alorii 3ero unui pointer este deci un ca3 special. Dbser1m de asemenea c 1ariabilele alloc(uf #i allocp snt declarate static cu scopul ca ele s fie locale numai fi#ierului surs care con+ine func+iile alloc #i free. K-emplul de mai sus demonstrea3 cte1a din facilit+ile aritmeticii de adrese 9pointeri<. @n primul rnd* pointerii pot fi compara+i n anumite situa+ii. $ac p #i I snt pointeri la membri unui acela#i masi1* atunci rela+iile <* <"* >* >"* ""* &" snt 1alide. Rela+ia p<I* de e-emplu* este ade1rat dac p indic un element mai apropiat de nceputul masi1ului dect elementul indicat de pointerul I. Comparrile ntre pointeri pot duce ns la re3ultate impre1i3ibile* dac ei se refer la elemente apar+innd la masi1e diferite. :e obser1 c pointerii #i ntregii pot fi aduna+i sau sc3u+i. Construc+ia de forma4 p%n nseamn adresa celui de2al n2lea element dup cel indicat de p* indiferent de tipul elementului pe care l indic p. Compilatorul C alinia3 1aloarea lui n conform dimensiunii elementelor pe care le
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

G8

indic p* dimensiunea fiind determinat din declara+ia lui p 9scara de aliniere este 7 pentru char* 8 pentru int etc<. $ac p #i I indic elemente ale aceluia#i masi1* p6I este numrul elementelor dintre cele pe care le indic p #i I. : scriem o alt 1ersiune a func+iei strlen folosind aceast ultim obser1a+ie4 strlen(char +s) { =W returnea3 lungimea unui #ir W= char +p; p " s; while (+p &" !\0!) p%%; return p6s; @n acest e-emplu s rmne constant cu adresa de nceput a #irului* n timp ce p a1ansea3 la urmtorul caracter de fiecare dat. $iferen+a p6s dintre adresa ultimului element al #irului #i adresa primului element al #irului indic numrul de elemente. @n afar de opera+iile binare men+ionate 9adunarea sau scderea pointerilor cu ntregi #i scderea sau compararea a doi pointeri<* celelalte opera+ii cu pointeri snt ilegale. &u este permis adunarea* nmul+irea* mpr+irea sau deplasarea pointerilor* dup cum nici adunarea lor cu constante de tip dou(le sau float. :nt admise de asemenea incrementrile #i decrementrile precum #i alte combina+ii ca de e-emplu +%%p #i +66p.

6.). Pointeri la caracter i #uncii


D constant #ir* de e-emplu4 "Cuna dimineata" este un masi1 de caractere* care n repre3entarea intern este terminat cu caracterul !\0!* astfel nct programul poate depista sfr#itul lui. Lungimea acestui #ir n memorie este astfel cu 7 mai mare dect numrul de caractere ce apar efecti1 ntre g"ilimelele de nceput #i sfr#it de #ir.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

G?

Cea mai frec1ent apari+ie a unei constante #ir este ca argument la func+ii* ca3 n care accesul la ea se reali3ea3 prin intermediul unui pointer. @n e-emplul4 printf("Cuna dimineata\n"); func+ia printf prime#te de fapt un pointer la masi1ul de caractere. @n prelucrarea unui #ir de caractere snt implica+i numai pointeri* limbajul C neoferind nici un operator care s trate3e #irul de caractere ca o unitate de informa+ie. Com pre3enta cte1a aspecte legate de pointeri #i masi1e anali3nd dou e-emple. : considerm pentru nceput func+ia strcp9(s,t) care copia3 #irul t peste #irul s. D prim 1ersiune a programului ar fi urmtoarea4 strcp9(char s)*, char t)*) {=W copia3 t peste s W= int t; i " 0; while ((s)i*"t)i*) &" !\0!) i%%; D a doua 1ersiune cu ajutorul pointerilor este urmtoarea4 strcp9(char +s, char +t) { =W 1ersiune cu pointeri W= while ((+s%%"+t%%) &" !\0!) ; 6ceast 1ersiune cu pointeri modific prin incrementare pe s #i t n partea de test. Caloarea lui +t%% este caracterul indicat de pointerul t* nainte de incrementare. &ota+ia postfi- %% asigur c t 1a fi modificat dup depunerea con+inutului indicat de el* la 1ec"ea po3i+ie a lui s* dup care #i s se incrementea3. Kfectul este c se copia3 caracterele #irului t n #irul s pn la caracterul terminal !\0! inclusi1.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

GA

6m mai putea face o obser1a+ie legat de redundan+a comparrii cu caracterul !\0!* redundan+ care re3ult din structura instruc+iunii while. bi atunci forma cea mai prescurtat a func+iei strcp9(s,t) este4 strcp9(char +s, char +t) { while (+s%% " +t%%) ; : considerm* ca al doilea e-emplu* func+ia strcmp(s,t) care compar caracterele #irurilor s #i t #i returnea3 o 1aloare negati1* 3ero sau po3iti1* dup cum #irul s este le-icografic mai mic* egal sau mai mare ca #irul t. Caloarea returnat se ob+ine prin scderea caracterelor primei po3i+ii n care s #i t difer. D prim 1ersiune a func+iei strcmp(s,t) este urmtoarea4 strcmp(char s, char t) {=W compar #irurile s #i t W= int i; i " 0; while (s)i*""t)i*) if (s)i%%*""!\0!) return 0; return s)i*6t)i*; Cersiunea cu pointeri a aceleia#i func+ii este4 strcmp(char +s, char +t) { for (; +s""+t; s%%,t%%) if (+s""!\0!) return 0; return +s6+t; @n final pre3entm func+ia strsa- care copia3 un #ir dat prin argumentul ei ntr2o 3on ob+inut printr2un apel la func+ia alloc.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

GB

Ka returnea3 un pointer la #irul copiat sau A?>>* dac nu mai e-ist suficient spa+iu pentru memorarea #irului. char +strsa-(char +s) { =W copia3 #irul s W= char +p; p " alloc(strlen(s)%'); if (p&"A?>>) strcp9(p,s); return p;

6.+. Masi$e multidimensionale


Limbajul C ofer facilitatea utili3rii masi1elor multidimensionale* de#i n practic ele snt folosite mai pu+in dect masi1ele de pointeri. : considerm problema con1ersiei datei* de la 3i din lun* la 3i din an #i in1ers* +innd cont de faptul c anul poate s fie bisect sau nu. $efinim dou func+ii care s reali3e3e cele dou con1ersii. Func+ia da9UofU9ear con1erte#te 3iua #i luna n 3iua anului #i func+ia monthUda9 con1erte#te 3iua anului n lun #i 3i. 6mbele func+ii au ne1oie de aceea#i informa+ie #i anume un tabel cu numrul 3ilelor din fiecare lun. $eoarece numrul 3ilelor din lun difer pentru anii bisec+i de cele pentru anii nebisec+i este mai u#or s considerm un tabel bidimensional n care prima linie s corespund numrului de 3ile ale lunilor pentru anii nebisec+i* iar a doua linie s corespund numrului de 3ile pentru anii bisec+i. @n felul acesta nu trebuie s +inem o e1iden+ n timpul calculului a ceea ce se ntmpl cu luna februarie. 6tunci masi1ul bidimensional care con+ine informa+iile pentru cele dou func+ii este urmtorul4 static int da9Uta().*)'0* " { {0,0',.5,0',00,0',00,0',0',00,0',00,0' , {0,0',.4,0',00,0',00,0',0',00,0',00,0' ;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

GE

%asi1ul da9Uta( trebuie s fie declarat e-tern pentru a putea fi folosit de ambele func+ii. @n limbajul C* prin defini+ie* un masi1 cu dou dimensiuni este n realitate un masi1 cu o dimensiune ale crui elemente snt masi1e. $e aceea indicii se scriu sub forma )i*)G* n loc de )i,G** cum se procedea3 n cele mai multe limbaje. ,n masi1 bidimensional poate fi tratat n acela#i fel ca #i n celelalte limbaje* n sensul c elementele snt memorate pe linie* adic indicele cel mai din dreapta 1aria3 cel mai rapid. ,n masi1 se ini+iali3ea3 cu ajutorul unei liste de ini+iali3atori nc"i#i ntre acolade; fiecare linie a unui masi1 bidimensional se ini+iali3ea3 cu ajutorul unei subliste de ini+iali3atori. @n ca3ul e-emplului nostru* masi1ul da9Uta( ncepe cu o coloan 3ero* pentru ca numerele lunilor s fie ntre 7 #i 78 #i nu ntre 0 #i 77* aceasta pentru a nu face modificri n calculul indicilor. bi atunci func+iile care reali3ea3 con1ersiile cerute de e-emplul nostru snt4 da9UofU9ear (int 9ear, int month, int da9) { =W 3iua anului din lun #i 3i W= int i, leap; leap " (9ear#/""0) $$ (9ear#'00&"0) HH (9ear#/00""0); for (i"'; i<month; i%%) da9 %" da9Uta()leap*)i*; return da9; $eoarece 1ariabila leap poate lua ca 1alori numai 3ero sau unu dup cum e-presia4 (9ear#/""0) $$ (9ear#'00&"0) HH (9ear#/00""0) este fals sau ade1rat* ea poate fi folosit ca indice de linie n tabelul da9Uta( care are doar dou linii n e-emplul nostru. monthUda9(int 9ear, int 9earda9,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

G7

int +pmonth, int +pda9) { int i,leap; leap " (9ear#/""0) $$ (9ear#'00&"0) HH (9ear#/00""0); for (i"'; 9earda9>da9Uta()leap*)i*; i%%) 9earda9 6" da9Uta()leap*)i*; +pmonth " i; +pda9 " 9earda9; $eoarece aceast ultim func+ie returnea3 dou 1alori* argumentele lun #i 3i 1or fi pointeri. Exemplu4 monthUda9('45/,2',$m,$d) 1a ncrca pe m cu ?* iar pe d cu 7 9adic 7 martie<. $ac un masi1 bidimensional trebuie transmis unei func+ii* declara+ia argumentelor func+iei trebuie s includ dimensiunea coloanei. $imensiunea liniei nu este necesar s apar n mod obligatoriu* deoarece ceea ce se transmite de fapt este un pointer la masi1e de cte 7? ntregi* n ca3ul e-emplului nostru. 6stfel* dac masi1ul da9Uta( trebuie transmis unei func+ii f* atunci declara+ia lui f poate fi4 f(int (+da9Uta())'0*) unde declara+ia (+da9Uta())'0*) indic faptul c argumentul lui f este un pointer la un masi1 de 7? ntregi. @n general deci* un masi1 d2dimensional a)i*)G*...)p* de rangul i+G+...+p este un masi1 d7 2 dimensional de rangul G+,+...+p ale crui elemente* fiecare* snt masi1e d8 2 dimensionale de rang ,+...+p ale crui elemente* fiecare* snt masi1e d? 2 dimensionale #.a.m.d. Dricare dintre e-presiile a)i** a)i*)G*...* a)i*)G*... )p* pot aprea n e-presii. 0rima are tipul masi1* ultima are tipul int* de e-emplu* dac masi1ul este de tipul int. Com mai re1eni asupra acestei probleme cu detalii.

6.4. Masi$e de pointeri i pointeri la pointeri


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

GG

$eoarece pointerii snt 1ariabile* are sens no+iunea de masi1 de pointeri. Com ilustra modul de lucru cu masi1e de pointeri pe un e-emplu. : scriem un program care s sorte3e le-icografic liniile de lungimi diferite ale unui te-t* linii care spre deosebire de ntregi nu pot fi comparate sau sc"imbate printr2o singur opera+ie. $ac memorm liniile te-tului una dup alta ntr2un masi1 lung de caractere 9gestionat de func+ia alloc<* atunci fiecare linie poate fi accesibil cu ajutorul unui pointer la primul ei caracter. 0ointerii tuturor liniilor* la rndul lor* pot fi memora+i sub forma unui masi1. 6tunci dou linii de te-t pot fi comparate transmi+nd pointerii lor func+iei strcmp. $ac dou linii care nu respect ordinea trebuie s fie sc"imbate* se sc"imb doar pointerii lor din masi1ul de pointeri #i nu te-tul efecti1 al liniilor. 0rocesul de sortare l 1om reali3a n trei pa#i4 7< se citesc toate liniile te-tului de la intrare; 8< se sortea3 liniile n ordine le-icografic; ?< se tipresc liniile sortate n noua ordine. Com scrie programul prin func+iile sale* fiecare func+ie reali3nd unul din cei trei pa#i de mai sus. D rutin principal 1a controla cele trei func+ii. Ka are urmtorul cod4 #define >JA@M '00 =W nr ma-im de linii de sortat W= main() { =W sortea3 liniile de la intrare W= char +lineptr)>JA@M*; =W pointeri la linii W= int nlines; =W nr linii intrare citite W= if ((nlines"readlines(lineptr,>JA@M))>"0) { sort(lineptr,nlines); writelines(lineptr,nlines); else printf ("Jntrarea prea mare pentru sort\n");

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

GH

Cele ? func+ii care reali3ea3 ntregul proces snt4 readlines* sort #i writelines. Rutina de intrare readlines trebuie s memore3e caracterele fiecrei linii #i s construiasc un masi1 de pointeri la liniile citite. /rebuie* de asemenea* s numere liniile din te-tul de la intrare* deoarece aceast informa+ie este necesar n procesul de sortare #i de imprimare. @ntruct func+ia de intrare poate prelucra numai un numr finit de linii de intrare* ea poate returna un numr ilegal* cum ar fi 7* spre a semnala c numrul liniilor de intrare este prea mare pentru capacitatea de care dispune. 6tunci func+ia readlines care cite#te liniile te-tului de la intrare este urmtoarea4 #define B<;>@A '000 #define A?>> 0 #define @S= 6' readlines(char +lineptr)*, int ma8lines) { =W cite#te liniile W= int len,nlines; char +p,+alloc(),line)B<;>@A*; nlines " 0; while ((len"7etline(line,B<;>@A))>0) if (nlines>"ma8lines) return 6'; else if ((p"alloc(len))""A?>>) return 6'; else { line)len6'* " !\0!; strcp9(p,line); lineptr)nlines%%* " p; return nlines; ;nstruc+iunea line)len6'* " !\0!; #terge caracterul <LF> de la sfr#itul fiecrei linii ca s nu afecte3e ordinea n care snt
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

H0

sortate liniile #i depune n locul lui caracterul !\0! ca marc de sfr#it de #ir. Rutina care tipre#te liniile n noua lor ordine este writelines #i are urmtorul cod4 writelines(char +lineptr)*, int nlines) { =W scrie liniile sortate W= int i; for (i"0; i<nlines; i%%) printf("#s\n",lineptr)i*); $eclara+ia nou care apare n aceste programe este4 char +lineptr)>JA@M*; care indic faptul c lineptr este un masi1 de >JA@M elemente* fiecare element al masi1ului fiind un pointer la un caracter. 6stfel lineptr)i* este un pointer la un caracter* iar WlineptrYi[ permite accesul la caracterul respecti1. $eoarece lineptr este el nsu#i un masi1* care se transmite ca argument func+iei writelines* el 1a fi tratat ca un pointer 91e3i sec+iunea H.?< #i atunci func+ia writelines mai poate fi scris #i astfel4 writelines(char +lineptr)*, int nlines) { while (66nlines>"0) printf("#s\n",+lineptr%%); @n func+ia printf* lineptr indic ini+ial prima linie de imprimat; fiecare incrementare a1ansea3 pe +lineptr la urmtoarea linie de imprimat* n timp ce nlines se mic#orea3 dup fiecare tiprire a unei linii cu 7. Func+ia care reali3ea3 sortarea efecti1 a liniilor se ba3ea3 pe algoritmul de njumt+ire #i are urmtorul cod4 #define A?>> 0 #define >JA@M '00
H7

=W nr ma-im de linii de sortat W=

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

sort(char +-)*, int n) { =W sortea3 #irurile -0* -'* ... -n6' n ordine cresctoare W= int 7ap,i,G; char +temp; for (7ap"nF.; 7ap>0; 7apF".) for (i"7ap; i<n; i%%) for (G"i67ap; G>"0; G6"7ap) { if (strcmp(-)G*,-)G%7ap*)<"0) (rea,; temp " -)G*; -)G* " -)G%7ap*; -)G%7ap* " temp;

$eoarece fiecare element al masi1ului - 9care este de fapt masi1ul lineptr< este un pointer la primul caracter al unei linii* 1ariabila temp 1a fi #i ea un pointer la un caracter* deci opera+iile de atribuire din ciclu dup 1ariabila G snt admise #i ele reali3ea3 rein1ersarea pointerilor la linii dac ele nu snt n ordinea cerut. : re+inem deci urmtoarele lucruri legate de masi1e #i pointeri. $e cte ori apare ntr2o e-presie un identificator de tip masi1 el este con1ertit ntr2un pointer la primul element al masi1ului. 0rin defini+ie* operatorul de inde-are )* este interpretat astfel nct E7)E8* este identic cu +((E7)%(E8)). $ac E7 este un masi1* iar E8 un ntreg* atunci E7)E8* se refer la elementul de indice E8 al masi1ului E7. D regul corespun3toare se aplic #i masi1elor multi2 dimensionale. $ac E7 este un masi1 d2dimensional* de rangul i+G+...+,* atunci ori de cte ori e7 apare ntr2o e-presie* e7 1a fi con1ertit ntr2un pointer la un masi1 d7 2 dimensional de rangul G+...+,* ale crui elemente snt masi1e. $ac operatorul + se aplic acestui pointer* re3ultatul este masi1ul d7 2 dimensional* care se 1a con1erti imediat ntr2un pointer la un masi1 d8 2 dimensional #.a.m.d. Ra+ionamentul se poate aplica n mod inducti1 pn cnd* n
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

H8

final* ca urmare a aplicrii operatorului + se ob+ine ca re3ultat un ntreg* de e-emplu* dac masi1ul a fost declarat de tipul int. : considerm* de e-emplu* masi1ul4 int 8)0*)1*; 8 este un masi1 de ntregi* de rangul ?WB. Cnd 8 apare ntr2o e-presie* el este con1ertit ntr2un pointer la 9primul din cele trei< masi1e de B ntregi.

@n e-presia 8)i** care este ec"i1alent cu e-presia +(8%i)* 8 este con1ertit ntr2un pointer la un masi1* ale crui elemente snt la rndul lor masi1e de B elemente; apoi i se con1erte#te la tipul 8* adic indicele i se nmul+e#te cu lungimea elementului pe care l indic 8 9adic B ntregi< #i apoi re3ultatele se adun. :e aplic operatorul + pentru ob+inerea masi1ului i 9de B ntregi< care la rndul lui este con1ertit ntr2un pointer la primul ntreg din cei cinci. :e obser1 deci c primul indice din declara+ia unui masi1 nu joac rol n calculul adresei.

6.5. Iniiali1area masi$elor i masi$elor de pointeri


;ni+iali3atorul unei 1ariabile declarate masi1 const dintr2o list de ini+iali3atori separa+i prin 1irgul #i nc"i#i ntre acolade* corespun3tori tuturor elementelor masi1ului. Ki snt scri#i n ordinea cresctoare a indicilor masi1ului. $ac masi1ul con+ine sub2masi1e atunci regula se aplic recursi1 membrilor masi1ului. $ac n lista de ini+iali3are e-ist mai pu+ini ini+iali3atori dect elementele masi1ului* restul elementelor neini+iali3ate se ini+iali3ea3 cu 3ero. &u se admite ini+iali3area unui masi1 de clas cu automatic. 6coladele { #i se pot omite n urmtoarele situa+ii4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

H?

5 dac ini+iali3atorul ncepe cu o acolad stng 9 {<* atunci lista de ini+iali3atori* separa+i prin 1irgul* 1a ini+iali3a elementele masi1ului; nu se accept s e-iste mai mul+i ini+iali3atori dect numrul elementelor masi1ului; 5 dac ns ini+iali3atorul nu ncepe cu acolad stng 9 {<* atunci se iau din lista de ini+iali3atori at+ia ini+iali3atori c+i corespund numrului de elemente ale masi1ului* restul ini+iali3atorilor 1or ini+iali3a urmtorul membru al masi1ului* care are ca parte 9sub2 masi1< masi1ul deja ini+iali3at. ,n masi1 de caractere poate fi ini+iali3at cu un #ir* ca3 n care caracterele succesi1e ale #irului ini+iali3ea3 elementele masi1ului. Exemple4 7< int 8)* " {',0,1 ; 6ceast declara+ie define#te #i ini+iali3ea3 pe 8 ca un masi1 unidimensional cu trei elemente* n ciuda faptului c nu s2a specificat dimensiunea masi1ului. 0re3en+a ini+iali3atorilor nc"i#i ntre acolade determin dimensiunea masi1ului. 8< $eclara+ia int 9)/*)0*"{ {',0,1 , {.,/,2 , {0,1,3 , ; este o ini+iali3are complet nc"is ntre acolade. Calorile 7*?*B ini+iali3ea3 prima linie a masi1ului 9)0* #i anume pe 9)0*)0** 9)0*)'** 9)0*).*. @n mod analog urmtoarele dou linii ini+iali3ea3 pe 9)'* #i 9).*. $eoarece ini+iali3atorii snt mai putini dect numrul elementelor masi1ului* linia 9)0* se 1a ini+iali3a cu 3ero* respecti1 elementele 9)0*)0** 9)0*)'** 9)0* ).* 1or a1ea 1alorile 3ero. ?< 6cela#i efect se poate ob+ine din declara+ia4 int 9)/*)0* " {',0,1,.,/,2,0,1,3 ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HA

unde ini+iali3atorul masi1ului 9 ncepe cu acolada stng n timp ce ini+iali3atorul pentru masi1ul 9)0* nu* fapt pentru care primii trei ini+iali3atori snt folosi+i pentru ini+iali3area lui 9)0** restul ini+iali3atorilor fiind folosi+i pentru ini+iali3area masi1elor 9)'* #i respecti1 9).*. A< $eclara+ia4 int 9)/*)0* " { {' ,{., ,{0, ,{/ ; ini+iali3ea3 masi1ul 9)0* cu 97*0*0<* masi1ul 9)'* cu 98*0*0<* masi1ul 9).* cu 9?*0*0< #i masi1ul 9)/* cu 9A*0*0<. B< $eclara+ia4 static char ms7)* " "@roare de sinta8a"; ini+iali3ea3 elementele masi1ului de caractere ms7 cu caracterele succesi1e ale #irului dat. @n ceea ce pri1e#te ini+iali3area unui masi1 de pointeri s considerm urmtorul e-emplu. Fie func+ia monthUname care returnea3 un pointer la un #ir de caractere care indic numele unei luni a anului. Func+ia dat con+ine un masi1 de #iruri de caractere #i returnea3 un pointer la un astfel de #ir* cnd ea este apelat. Codul func+iei este urmtorul4 char +monthUname(int n) { =W returnea3 numele lunii a n2a W= static char +name)* " { "luna ile7ala", "ianuarie", "fe(ruarie", "martie", "aprilie", "mai", "iunie", "iulie", "au7ust",
"septem(rie", "octom(rie", "noiem(rie", "decem(rie"

return ((n<') HH (n>'.)) O name)0* P name)n* ;


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HB

@n acest e-emplu* name este un masi1 de pointeri la caracter* al crui ini+iali3ator este o list de #iruri de caractere. Compilatorul aloc o 3on de memorie pentru memorarea acestor #iruri #i generea3 cte un pointer la fiecare din ele pe care apoi i introduce n masi1ul name. $eci name)i* 1a con+ine un pointer la #irul de caractere a1nd indice i al ini+iali3atorului. $imensiunea masi1ului name nu este necesar a fi specificat deoarece compilatorul o calculea3 numrnd ini+iali3atorii furni3a+i #i o completea3 n declara+ia masi1ului.

6.6. Masi$e de pointeri i masi$e multidimensionale


6desea se creea3 confu3ii n ceea ce pri1e#te diferen+a dintre un masi1 bidimensional #i un masi1 de pointeri. Fie date declara+iile4 int a)'0*)'0*; int +()'0*; @n aceast declara+ie a este un masi1 de ntregi cruia i se aloc spa+iu pentru toate cele 700 de elemente* iar calculul indicilor se face n mod obi#nuit pentru a a1ea acces la oricare element al masi1ului. 0entru masi1ul (* declara+ia aloc spa+iu numai pentru 3ece pointeri* fiecare trebuind s fie ncrcat cu adresa unui masi1 de ntregi. 0resupunnd c fiecare pointer indic un masi1 de 3ece elemente nseamn c ar trebui alocate nc o sut de loca+ii de memorie pentru elementele masi1elor. @n aceast accep+iune* folosirea masi1elor a #i ( poate fi similar n sensul c a)1*)1* #i ()1*)1** de e-emplu* se refer ambele la unul #i acela#i ntreg 9dac fiecare element ()i* este ini+iali3at cu adresa masi1ului a)i*<. 6stfel* masi1ul de pointeri utili3ea3 mai mult spa+iu de memorie dect masi1ele bidimensionale #i pot cere un pas de ini+iali3are e-plicit. $ar masi1ele de pointeri pre3int dou a1antaje* #i anume4 accesul la un element se face cu adresare indirect* prin intermediul
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HE

unui pointer* n loc de procedura obi#nuit folosind nmul+irea #i apoi adunarea* iar al doilea a1antaj const n aceea c dimensiunea masi1elor pointate poate fi 1ariabil. 6cest lucru nseamn c un element al masi1ului de pointeri ( poate indica un masi1 de 3ece elemente* altul un masi1 de dou elemente #i altul de e-emplu poate s nu indice nici un masi1. Cu toate c problema pre3entat n acest paragraf am descris2o n termenii ntregilor* ea este cel mai frec1ent utili3at n memorarea #irurilor de caractere de lungimi diferite 9ca n func+ia monthUname pre3entat mai sus<.

6.17. :rgumentele unei linii de comand


@n sistemul de calcul care admite limbajul C trebuie s e-iste posibilitatea ca n momentul e-ecu+iei unui program scris n acest limbaj s i se transmit acestuia argumente sau parametri prin linia de comand. Cnd un program este lansat n e-ecu+ie #i func+ia main este apelat* apelul 1a con+ine dou argumente. 0rimul argument 9numit con1en+ional ar7c< repre3int numrul de argumente din linia de comand care a lansat programul. 6l doilea argument 9ar7-< este un pointer la un masi1 de pointeri la #iruri de caractere care con+in argumentele* cte unul pe #ir. : ilustrm acest mod dinamic de comunicare ntre utili3ator #i programul su printr2un e-emplu. Fie programul numit pri care dorim s imprime la terminal argumentele lui luate din linia de comand* imprimarea fcndu2se pe o linie* iar argumentele imprimate s fie separate prin spa+ii. Comanda4 pri succes cole7i 1a a1ea ca re3ultat imprimarea la terminal a te-tului succes cole i 0rin con1en+ie* ar7-)0* este un pointer la numele pri al programului apelat* astfel c ar7c* care specific numrul de argumente din linia de comand este cel pu+in 7.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

H7

@n e-emplul nostru* ar7c este ?* iar ar7-)0** ar7-)'* #i ar7-).* snt pointeri la "pri"* "succes" #i respecti1 "cole7i". 0rimul argument real este ar7-)'* iar ultimul este ar7-)ar7c6'*. $ac ar7c este 7* nseamn c linia de comand nu are nici un argument dup numele programului. 6tunci programul pri are urmtorul cod4 main(int ar7c, char +ar7-)*) { =W tipre#te argumentele W= int i; for (i"'; i<ar7c; i%%) printf("#s##c",ar7-)i*,(i<ar7c6')O ! !P!\n!); $eoarece ar7- este un pointer la un masi1 de pointeri* e-ist mai multe posibilit+i de a scrie acest program. : mai scriem dou 1ersiuni ale acestui program. main(int ar7c, char +ar7-)*) { =W 1ersiunea a doua W= while (66ar7c>0) printf("#s#c",+%%ar7-,(ar7->')O ! !P!\n!); $eoarece ar7- este un pointer la un masi1 de pointeri* incrementndu2l* (%%ar7-)* el 1a pointa la ar7-)'* n loc de ar7-)0*. Fiecare incrementare succesi1 po3i+ionea3 pe ar7- la urmtorul argument* iar +ar7- este pointerul la argumentul #irului respecti1. @n acela#i timp ar7c este decrementat pn de1ine 3ero* moment n care nu mai snt argumente de imprimat. 6lternati14 main(int ar7c, char +ar7-) *) { =W 1ersiunea a treia W= while (66ar7c>0)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HG

printf((ar7c>')O "#s "P"#s\n",+%%ar7-); 6ceast 1ersiune arat c argumentul func+iei printf poate fi o e-presie ca oricare alta* cu toate c acest mod de utili3are nu este foarte frec1ent. Ca un al doilea e-emplu* s reconsiderm programul din sec+iunea 7.B* care imprim fiecare linie a unui te-t care con+ine un #ir specificat de caractere 9sc"em<. $orim acum ca aceast sc"em s poat fi modificat dinamic* de la e-ecu+ie la e-ecu+ie. 0entru aceasta o specificm printr2un argument n linia de comand. bi atunci programul care caut sc"ema dat de primul argument al liniei de comand este4 #define B<;>JA@ '000 main(int ar7c, char +ar7-) *) { =W gse#te sc"ema din primul argument W= char line)B<;>JA@*; if (ar7c&".) printf(">inia de comanda eronata\n"); else while (7etline(line,B<;>JA@)>0) if (inde8(line,ar7-)'*)>"0) printf("#s",line); unde linia de comand este de e-emplu4 "find lim(aG" n care "find" este numele programului* iar "lim(aG" este sc"ema cutat. Re3ultatul 1a fi imprimarea tuturor liniilor te-tului de intrare care con+in cu1ntul "lim(aG". : elaborm acum modelul de ba3* legat de linia de comand #i argumentele ei. : presupunem c dorim s introducem n linia de comand dou argumente op+ionale4 unul care s tipreasc toate liniile cu e-cep+ia acelora care con+in sc"ema* #i al doilea care s precead fiecare linie tiprit cu numrul ei de linie.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HH

D con1en+ie pentru programele scrise n limbajul C este ca argumentele dintr2o linie de comand care ncep cu un semn ' 6' s introduc un parametru op+ional. $ac alegem* de e-emplu* 68 pentru a indica cu e-cep+ia #i 6n pentru a cere numrarea liniilor* atunci comanda4 find 68 6n la a1nd intrarea4 la miezul stinselor lumini s-a,un victoriosla temelii- la rdcinila mduv- la os" 1a produce tiprirea liniei a doua* precedat de numrul ei* deoarece aceast linie nu con+ine sc"ema "la". 6rgumentele op+ionale snt permise n orice ordine n linia de comand. 6nali3area #i prelucrarea argumentelor unei linii de comand trebuie efectuat n func+ia principal main* ini+iali3nd n mod corespun3tor anumite 1ariabile. Celelalte func+ii ale programului nu 1or mai +ine e1iden+a acestor argumente. Kste mai comod pentru utili3ator dac argumentele op+ionale snt concatenate* ca n comanda4 find 68n la Caracterele !8! respecti1 !n! indic doar absen+a sau pre3en+a acestor op+iuni 9s'itc"< #i nu snt tratate din punct de 1edere al 1alorii lor. Fie programul care caut sc"ema "la" n liniile de la intrare #i le tipre#te pe acelea* care nu con+in sc"ema* precedate de numrul lor de linie. 0rogramul tratea3 corect* att prima form a liniei de comand ct #i a doua. #define B<;>JA@ '000 main(int ar7c, char +ar7-)*) { =W caut sc"ema W= char line)B<;>JA@*, +s;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

700

lon7 line0; int e8cept, num(er; line0 " 0; num(er " 0; while (66ar7c>0 $$ (+%%ar7-))0*""!6!) for (s"ar7-)0*%'; +s&"!\0!; s%%) switch(+s) { case !8!P e8cept " '; (rea,; case !n!P num(er " '; (rea,; defaultP printf ("findP optiune ile7ala #c\n", +s); ar7c " 0; (rea,; if (ar7c&"') printf ("Au e8ista ar7umente sau schema\n"); else while (7etline(line,B<;>JA@)>0) { line0%%; if ((inde8(line,+ar7-)>"0)&"e8cept) { if (num(er) printf("#dP",line0); printf("#s",line);

$ac nu e-ist erori n linia de comand* atunci la sfr#itul primului ciclu '"ile ar7c trebuie s fie 7* iar +ar7- con+ine adresa sc"emei. +%%ar7- este un pointer la un #ir argument* iar (+% %ar7-))0* este primul caracter al #irului. @n aceast ultim e-presie parante3ele snt necesare deoarece fr ele e-presia nseamn +%%(ar7-)0*) ceea ce este cu totul altce1a 9#i gre#it<4 al
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

707

doilea caracter din numele programului. D alternati1 corect pentru (+%%ar7-)0*) este ++%%ar7-.

6.11. Pointeri la #uncii


@n limbajul C o func+ie nu este o 1ariabil* dar putem defini un pointer la o func+ie* care apoi poate fi prelucrat* transmis unor alte func+ii* introdus ntr2un masi1 #i a#a mai departe. Relati1 la o func+ie se pot face doar dou opera+ii4 apelul ei #i considerarea adresei ei. $ac numele unei func+ii apare ntr2o e-presie* fr a fi urmat imediat de o parante3 stng* deci nu pe po3i+ia unui apel la ea* atunci se generea3 un pointer la aceast func+ie. 0entru a transmite o func+ie unei alte func+ii* ca argument* se poate proceda n felul urmtor4 int f(); 7(f); unde func+ia f este un argument pentru func+ia 7. $efini+ia func+iei 7 1a fi4 7(int(+funcpt) ()) { (+funcpt)(); Func+ia f trebuie declarat e-plicit n rutina apelant 9 int f();<* deoarece apari+ia ei n 7(f) nu a fost urmat de parante3 stng a(a. @n e-presia 7(f) f nu apare pe po3i+ia de apel de func+ie. @n acest ca3* pentru argumentul func+iei 7 se generea3 un pointer la func+ia f. $eci 7 apelea3 func+ia f printr2un pointer la ea. $eclara+iile din func+ia 7 trebuie studiate cu grij. int (+funcpt)(); spune c funcpt este un pointer la o func+ie care returnea3 un ntreg. 0rimul set de parante3e este necesar* deoarece fr el int +funcpt(); nseamn c funcpt este o func+ie care returnea3 un pointer la un ntreg* ceea ce este cu totul diferit fa+ de sensul primei e-presii. Folosirea lui funcpt n e-presia4 (+funcpt)();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

708

indic faptul c funcpt este un pointer la o func+ie* +funcpt este func+ia* iar (+funcpt)() este apelul func+iei. D form ec"i1alent simplificat de apel este urmtoarea4 funcpt(); Ca un e-emplu* s considerm procedura de sortare a liniilor de la intrare* descris n sec+iunea H.7* dar modificat n sensul ca dac argumentul op+ional 6n apare n linia de comand* atunci liniile se 1or sorta nu le-icografic ci numeric* liniile con+innd grupe de numere. D sortare const adesea din trei pr+i4 o comparare care determin ordinea oricrei perec"i de elemente* un sc"imb care in1ersea3 ordinea elementelor implicate #i un algoritm de sortare care face comparrile #i in1ersrile pn cnd elementele snt aduse n ordinea cerut. 6lgoritmul de sortare este independent de opera+iile de comparare #i in1ersare* astfel nct transmi+nd diferite func+ii de comparare #i in1ersare func+iei de sortare* elementele de intrare se pot aranja dup diferite criterii. Compararea le-icografic a dou linii se reali3ea3 prin func+iile strcmp #i swap. %ai a1em ne1oie de o rutin numcmp care s compare dou linii pe ba3a 1alorilor numerice #i care s returne3e aceia#i indicatori ca #i rutina strcmp. $eclarm aceste trei func+ii n func+ia principal main* iar pointerii la aceste func+ii i transmitem ca argumente func+iei sort* care la rndul ei 1a apela aceste func+ii prin intermediul pointerilor respecti1i. Func+ia principal main 1a a1ea atunci urmtorul cod4 #define >JA@M '00 =W nr ma-im de linii de sortat W= main (int ar7c, char +ar7-)*) { char +lineptr)>JA@M*; =W pointeri la linii te-t W= int nlines; =W numr de linii citite W= int strcmp(), numcmp(); =W func+ii de comparare W= int swap (); =W func+ia de in1ersare W= int numeric; numeric " 0; =W 7 dac sort numeric W=
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70?

if (ar7c>' $$ ar7-)'*)0*""!6! $$ ar7-)'*)'*""!n!) numeric " '; if ((nlines"readlines(lineptr,>JA@M))>"0) { if (numeric) sort(lineptr,nlines,numcmp,swap); else sort(lineptr,nlines,strcmp,swap); writelines (lineptr,nlines); else printf ("Ar de linii de intrare prea mare\n"); @n apelul func+iei sort* argumentele strcmp* numcmp #i swap snt adresele func+iilor respecti1e. $eoarece ele au fost declarate func+ii care returnea3 un ntreg* operatorul a $a nu este necesar s precead numele func+iilor* compilatorul fiind cel care gestionea3 transmiterea adreselor func+iilor. Func+ia sort care aranjea3 liniile n ordinea cresctoare se 1a modifica astfel4 sort(char +-)*, int n, int (+comp)(), int (+e8ch)()) { =W sortea3 -0* -'* ... * -n' W= int 7ap,i,G; for (7ap"nF.; 7ap>0; 7apF".) for (i"7ap; i<n; i%%) for (G"i67ap; G>"0; G6"7ap) { if (comp(-)G*,-)G%7ap*)<"0) (rea,; e8ch(-%G,-%G%7ap);

: studiem declara+iile din aceast func+ie. int(+comp)(), (+e8ch)();


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70A

indic faptul c comp #i e8ch snt pointeri la func+ii care returnea3 un ntreg 9primul set de parante3e este necesar<. if (comp(-)G*,-)G%7ap*)<"0) nseamn apelul func+iei comp 9adic strcmp sau numcmp<* deoarece comp este un pointer la func+ie* +comp este func+ia* iar comp(-)G*,-)G%7ap*) este apelul func+iei. e8ch(-%G,-%G%7ap) este apelul func+iei swap* de in1ersare a dou linii* in1ersare care reali3ea3 intersc"imbarea adreselor liniilor implicate 91e3i sec+iunea H.8<. Func+ia numcmp este urmtoarea4 numcmp(char +s', char +s.) { =W compar s' #i s. numeric W= dou(le atof(),-',-.; -' " atof(s'); -. " atof(s.); if (-'<-.) return 6'; else if (-'>-.) return '; else return 0; 0entru ca programul nostru s fie complet s mai pre3entm #i codul func+iei swap* care sc"imb ntre ei pointerii a dou linii. swap(char +p8)*, char +p9)*) { char +temp; temp " +p8; +p8 " +p9; +p9 " temp;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70B

17. ,tructuri i reuniuni


D structur este o colec+ie de una sau mai multe 1ariabile* de acela#i tip sau de tipuri diferite* grupate mpreun sub un singur nume pentru a putea fi tratate mpreun 9n alte limbaje* structurile se numesc articole<. :tructurile ajut la organi3area datelor complicate* n special n programele mari* deoarece permit unui grup de 1ariabile legate s fie tratate ca o singur entitate. Com ilustra n acest capitol modul de utili3are a structurilor.

17.1. 3lemente de ba1


: re1enim asupra rutinei de con1ersie a datei pre3entat n capitolul H. D dat const din 3i* lun #i an* e1entual numrul 3ilei din an #i numele lunii. 6ceste cinci 1ariabile pot fi grupate ntr2o singur structur astfel4 struct date { int da9; int month; int 9ear; int 9earda9; char monUname)/*; ; Cu1ntul c"eie struct introduce o declara+ie de structur care este o list de declara+ii nc"ise n acolade. Cu1ntul struct poate fi urmat op+ional de un nume* numit marcaj de structur sau etic"et de structur* cum este n e-emplul nostru numele date. 6cest marcaj denume#te acest tip de structur #i poate fi folosit n continuare ca o prescurtare pentru declara+ia de structur detaliat creia i este asociat.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70E

Klementele sau 1ariabilele men+ionate ntr2o structur se numesc membri ai structurii. ,n membru al structurii sau o etic"et #i o 1ariabil oarecare* nemembru* pot a1ea acela#i nume fr a genera conflicte* deoarece ele 1or fi ntotdeauna deosebite una de alta din conte-t. 6colada dreapt care nc"eie o list de membri ai unei structuri poate fi urmat de o list de 1ariabile* la fel ca #i n ca3ul tipurilor de ba3. $e e-emplu4 struct {. . . 8,9,:; este din punct de 1edere sintactic analog cu4 int 8,9,:; n sensul c fiecare declara+ie declar pe 8* 9 #i : ca 1ariabile de tipul numit 9structur n primul ca3 #i ntreg n al doilea< #i cau3ea3 alocarea de spa+iu pentru ele. D declara+ie de structur care nu este urmat de o list de 1ariabile nu aloc memorie; ea descrie numai un #ablon* o form de structur. $ac structura este marcat sau etic"etat* atunci marcajul ei poate fi folosit mai tr3iu pentru definirea unor alte 1ariabile de tip structur* cu acela#i #ablon ca structura marcat. $e e-emplu* fiind dat declara+ia4 struct date d; ea define#te 1ariabila d* ca o structur de acela#i fel 9#ablon< ca structura date. D structur e-tern sau static poate fi ini+iali3at* ata#nd dup defini+ia ei o list de ini+iali3atori pentru componente* de e-emplu4 struct date d " {/,3,'45/,'51,"iulie" ; ,n membru al unei structuri este referit printr2o e-presie de forma4 nume-structur.membru n care operatorul membru de structur a .a leag numele membrului de numele structurii. Ca e-emplu fie atribuirea4 leap " (d.9ear#/""0) $$ (d.9ear#'00&"0) HH (d.9ear#/00""0); sau 1erificarea numelui lunii4 if (strcmp(d.monUname,"au7ust")""0) ...
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

707

:tructurile pot fi imbricate; o nregistrare de stat de plat* de e-emplu* poate fi de urmtoarea form4 struct person { char name)A<B@MJT@*; char address)<EVMJT@*; lon7 :ipcode; lon7 ssUnum(er; dou(le salar9; struct date (irthdate; struct date hiredate; ; :tructura person con+ine dou structuri de #ablon date. $eclara+ia4 struct person emp; define#te #i aloc o structur cu numele emp de acela#i #ablon ca #i person. 6tunci4 emp.(irthdate.month se refer la luna de na#tere. Dperatorul de membru de structur a .a este asociati1 de la stnga la dreapta.

17.2. ,tructuri i #uncii


K-ist un numr de restric+ii asupra structurilor n limbajul C. :ingurele opera+ii care se pot aplica unei structuri snt accesul la un membru al structurii #i considerarea adresei ei cu ajutorul operatorului $. 6cest lucru implic faptul c structurile nu pot fi atribuite sau copiate ca entit+i #i c ele nu pot fi transmise ca argumente la func+ii #i nici returnate din func+ii. :tructurile de clas automatic* ca #i masi1ele de aceea#i clas* nu pot fi ini+iali3ate; pot fi ini+iali3ate numai structurile e-terne #i statice* regulile de ini+iali3are fiind acelea#i ca pentru masi1e. 0ointerii la structuri nu se supun ns acestor restric+ii* moti1 pentru care structurile #i func+iile pot coe-ista #i conlucra prin intermediul pointerilor.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70G

Ca un e-emplu* s rescriem programul de con1ersie a datei* care calculea3 3iua anului* din lun #i 3i. da9UofU9ear(struct date +pd) { =W calculul 3ilei anului W= int i, da9, leap; da9 " pd6>da9; leap " (pd6>9ear#/""0) $$ (pd6>9ear#'00&""0) HH (pd6>9ear#/00""0); for (i"'; i<pd6>month; i%%) da9 %" da9Uta()leap*)i*; return da9; $eclara+ia4 struct date + pd; indic faptul c pd este un pointer la o structur de #ablonul lui date. &ota+ia4 pd6>9ear indic faptul c se refer membrul S 9earS al acestei structuri. @n general* dac p este un pointer la o structur p6>membru-structur se refer la un membru particular 9operatorul a 6>a se formea3 din semnul minus urmat de semnul mai mare<. $eoarece pd este pointer la o structur* membrul )ear poate fi de asemenea referit prin4 (+pd).9ear &ota+ia S6>S se impune ca un mod con1enabil de prescurtare. @n nota+ia (+pd).9ear* parante3ele snt necesare deoarece preceden+a operatorului membru de structur a .a este mai mare dect cea a operatorului +. 6mbii operatori a.a #i a6>a snt asociati1i de la stnga la dreapta* astfel nct4 p6>I6>membru emp.(irthdate.month snt de fapt4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

70H

(p6>I)6>membru (emp.(irthdate).month Dperatorii a6>a #i a.a ai structurilor* mpreun cu () pentru listele de argumente #i )* pentru inde-are se gsesc n 1rful listei de preceden+ 91e3i sec+iunea A.7E<* fiind din acest punct de 1edere foarte apropia+i. 6stfel* fiind dat declara+ia4 struct { int 8; int +9; +p; unde p este un pointer la o structur* atunci e-presia4 %%p6>8 incrementea3 pe 8* nu pointerul p* deoarece operatorul a6>a are o preceden+ mai mare dect a %%a. 0arante3ele pot fi folosite pentru a modifica ordinea operatorilor dat de preceden+a. 6stfel4 (%%p)6>8 incrementea3 mai nti pe p #i apoi accesea3 elementul 8* din structura nou pointat. @n e-presia (p%%)6>8 se accesea3 mai nti 8* apoi se incrementea3 pointerul p. @n mod analog* +p6>9 indic con+inutul adresei pe care o indic 9. K-presia +p6>9%% accesea3 mai nti ceea ce indic 9 #i apoi incrementea3 pe 9. K-presia (+p6>9)%% incrementea3 ceea ce indic 9. K-presia +p%%6>9 accesea3 ceea ce indic 9 #i apoi incrementea3 pointerul p.

17.3. Masi$e de structuri


:tructurile snt n mod special utile pentru tratarea masi1elor de 1ariabile legate prin conte-t. 0entru e-emplificare 1om considera un program care numr intrrile fiecrui cu1nt c"eie dintr2un te-t. 0entru aceasta a1em ne1oie de un masi1 de #iruri de caractere* pentru pstrarea numelor cu1intelor c"eie #i un masi1 de ntregi pentru a memora numrul apari+iilor. D posibilitate este de a folosi dou masi1e paralele ,e9word #i ,e9count declarate prin4 char +,e9word)AN@WM*;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

770

int ,e9count)AN@WM*; respecti1 unul de pointeri la #iruri de caractere #i cellalt de ntregi. Fiecrui cu1nt c"eie i corespunde perec"ea4 char +,e9word; int ,e9count; astfel nct putem considera cele dou masi1e ca fiind un masi1 de perec"i. 6tunci* declara+ia de structur4 struct ,e9 { char +,e9word; int ,e9count; ,e9ta()AN@WM*; define#te un masi1 ,e9ta( de structuri de acest tip #i aloc memorie pentru ele. Fiecare element al masi1ului ,e9ta( este o structur de acela#i #ablon ca #i structura ,e9. $efini+ia masi1ului ,e9ta( poate fi scris #i sub forma4 struct ,e9 { char +,e9word; int ,e9count; ; struct ,e9 ,e9ta()AN@WM*; $eoarece masi1ul de structuri ,e9ta( con+ine* n ca3ul nostru* o mul+ime constant de cu1inte c"eie* este mai u#or de ini+iali3at o dat pentru totdeauna c"iar n locul unde este definit. ;ni+iali3area structurilor este o opera+ie analoag cu ini+iali3area unui masi1 n sensul c defini+ia este urmat de o list de ini+iali3atori nc"i#i n acolade. 6tunci ini+iali3area masi1ului de structuri ,e9ta( 1a fi urmtoarea4 struct ,e9 { char + ,e9word; int ,e9count; ,e9ta()* " { "(rea,",0, "case",0,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

777

"char",0, =W ... W= "while",0 ; ;ni+iali3atorii snt perec"i care corespund la membrii structurii. ;ni+iali3area ar putea fi fcut #i inclu3nd ini+iali3atorii fiecrei structuri din masi1 n acolade ca n4 {"(rea,",0 ,{"case",0 .... dar parante3ele interioare nu snt necesare dac ini+iali3atorii snt 1ariabile simple sau #iruri de caractere #i dac to+i ini+iali3atorii snt pre3en+i. Compilatorul 1a calcula* pe ba3a ini+iali3atorilor* dimensiunea masi1ului de structuri ,e9ta( moti1 pentru care* la ini+iali3are* nu este necesar indicarea dimensiunii masi1ului. 0rogramul de numrare a cu1intelor c"eie ncepe cu definirea masi1ului de structuri ,e9ta(. Rutina principal main cite#te te-tul de la intrare prin apel repetat la o func+ie 7etword* care e-trage din intrare cte un cu1nt la un apel. Fiecare cu1nt este apoi cutat n tabelul ,e9ta( cu ajutorul unei func+ii de cutare (inar9* descris n sec+iunea 7.B. Lista cu1intelor c"eie trebuie s fie n ordine cresctoare pentru ca func+ia (inar9 s lucre3e corect. $ac cu1ntul cercetat este un cu1nt c"eie atunci func+ia (inar9 returnea3 numrul de ordine al cu1ntului n tabelul cu1intelor c"eie* altfel returnea3 7. #define B<;XSVE .0 (inar9(char +word, struct ,e9 ta()*, int n) { int low,hi7h,mid,cond; low " 0; hi7h " n 6 '; while (low<"hi7h) { mid "(low % hi7h) F .; if ( (cond"strcmp(word,ta()mid*.,e9word)) <0)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

778

hi7h " mid 6 '; else if (cond>0) low " mid % '; else return mid; return 6'; main() { =W numr cu1intele c"eie W= int n,t; char word)B<;XSVE*; while ((t"7etword(word,B<;XSVE))&"@S=) if (t"">@RR@V) if ( (n"(inar9(word,,e9ta(,AN@WM)) >"0) ,e9ta()n*.,e9count%%; for (n"0; n<AN@WM; n%%) if (,e9ta()n*.,e9count>0) printf("#/d #s\n", ,e9ta()n*.,e9count, ,e9ta()n*.,e9word); @nainte de a scrie func+ia 7etword este suficient s spunem c ea returnea3 constanta simbolic >@RR@V de fiecare dat cnd gse#te un cu1nt n te-tul de intrare #i copia3 cu1ntul n primul ei argument. Cantitatea AN@WM este numrul cu1intelor c"eie din ,e9ta( 9dimensiunea masi1ului de structuri<. $e#i putem calcula acest numr manual* este mai simplu #i mai sigur s2o facem cu calculatorul* mai ales dac lista cu1intelor c"eie este supus modificrilor. D posibilitate de a calcula AN@WM cu calculatorul este de a termina lista ini+iali3atorilor cu un pointer A?>> #i apoi prin ciclare pe ,e9ta( s detectm sfr#itul lui. 6cest lucru este mai mult dect necesar deoarece dimensiunea masi1ului de structuri este perfect
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77?

determinat n momentul compilrii. &umrul de intrri se determin mpr+ind dimensiunea masi1ului la dimensiunea structurii ,e9. Dperatorul si:eof descris n sec+iunea A.8 furni3ea3 dimensiunea n octe+i a argumentului su. @n ca3ul nostru* numrul cu1intelor c"eie este dimensiunea masi1ului ,e9ta( mpr+it la dimensiunea unui element de masi1. 6cest calcul este fcut ntr2o linie #define pentru a da o 1aloare identificatorului AN@WM4 #define AN@WM (si:eof(,e9ta() F si:eof(struct ,e9)) : re1enim acum la func+ia 7etword. 0rogramul pe care2l 1om da pentru aceast func+ie este mai general dect este necesar n aplica+ia noastr* dar nu este mult mai complicat. Func+ia 7etword cite#te cu1ntul urmtor din te-tul de intrare* printr2un cu1nt n+elegndu2se fie un #ir de litere #i cifre* cu primul caracter liter* fie un singur caracter. Func+ia returnea3 constanta simbolic >@RR@V dac a gsit un cu1nt* @S= dac a detectat sfr#itul fi#ierului sau caracterul nsu#i* dac el nu a fost alfabetic. 7etword(char +w, int lim) {=W cite#te un cu1nt W= int t; while (66lim>0) { t " t9pe(+w%%"7etchar()); if (t""@S=) return @S=; if (t&">@RR@V $$ t&"EJYJR) (rea,; +(w6') " !\0!; return >@RR@V; Func+ia 7etword apelea3 func+ia t9pe pentru identificarea tipului fiecrui caracter citit la intrare cu ajutorul func+iei 7etchar. Cersiunea func+iei t9pe pentru caractere 6:C;; este4 t9pe(int c) { =W returnea3 tipul caracterului W=
77A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

if (c>"!a! $$ c<"!:! HH c>"!<! $$ c<"!T!) return >@RR@V; if (c>"!0! $$ c<"!4!) return EJYJR; return c; Constantele simbolice >@RR@V #i EJYJR pot a1ea orice 1aloare care nu 1ine n contradic+ie cu caracterele nealfabetice #i KDF. Calori posibile pot fi4 #define >@RR@V !a! #define EJYJR !0!

17.'. Pointeri la structuri


0entru a ilustra modul de corelare dintre pointeri #i masi1ele de structuri* s rescriem programul de numrare a cu1intelor c"eie dintr2 un te-t* de data aceasta folosind pointeri* n loc de indici de masi1. $eclara+ia e-tern a masi1ului de structuri ,e9ta( nu necesit modificri* n timp ce func+iile main #i (inar9 da. 0re3entm* n continuare* aceste func+ii modificate. #define B<;XSVE .0 struct ,e9 +(inar9(char +word, struct ,e9 ta()*, int n) { =W caut cu1nt W= int cond; struct ,e9 + low; struct ,e9 +hi7h; struct ,e9 +mid; low " $ta()0*; hi7h " $ta()n6'*; while (low<"hi7h) { mid " low % (hi7h6low) F .; if ((cond"strcmp(word,mid6>,e9word))<0) hi7h " mid 6 '; else if (cond>0)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77B

low " mid % '; else return mid; return A?>>; main() { =W numr cu1intele c"eie* 1ersiune cu pointeri W= int t; char word)B<;XSVE*; struct ,e9 +(inar9(), +p; while ((t"7etword(word.B<;XSVE))&"@S=) if (t"">@RR@V) if ((p"(inar9(word,,e9ta(,AN@WM)) &" A?>>) p6>,e9count%%; for (p",e9ta(; p<,e9ta(%AN@WM; p%%) if (p6>,e9count>0) printf("#/d #s\n",p6>,e9count, p6>,e9word); : obser1m cte1a lucruri importante n acest e-emplu. @n primul rnd* declara+ia func+iei (inar9 trebuie s indice c ea returnea3 un pointer la o structur de acela#i #ablon cu structura ,e9* n loc de un ntreg. 6cest lucru este declarat att n func+ia principal main ct #i n func+ia (inar9. $ac (inar9 gse#te un cu1nt n structura ,e9* atunci returnea3 un pointer la el; dac nu27 gse#te* returnea3 A?>>. @n func+ie de aceste dou 1alori returnate* func+ia main semnalea3 gsirea cu1ntului prin incrementarea cmpului ,e9count corespun3tor cu1ntului sau cite#te urmtorul cu1nt. @n al doilea rnd* toate opera+iile de acces la elementele masi1ului de structuri ,e9ta( se fac prin intermediul pointerilor. 6cest lucru determin o modificare semnificati1 n func+ia (inar9. Calculul elementului mijlociu nu se mai poate face simplu prin4 mid " (low % hi7h) F .
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77E

deoarece adunarea a doi pointeri este o opera+ie ilegal* nedefinit. 6ceast instruc+iune trebuie modificat n4 mid " low % (hi7h6low) F . care face ca mid s pointe3e elementul de la jumtatea distan+ei dintre low #i hi7h. : mai obser1m ini+iali3area pointerilor low #i hi7h* care este perfect legal* deoarece este posibil ini+iali3area unui pointer cu o adres a unui element deja definit. @n func+ia main a1em urmtorul ciclu4 for(p",e9ta(; p<,e9ta(%AN@WM; p%%)... $ac p este un pointer la un masi1 de structuri* orice opera+ie asupra lui p +ine cont de dimensiunea unei structuri* astfel nct p%% incrementea3 pointerul p la urmtoarea structur din masi1* adunnd la p dimensiunea corespun3toare a unei structuri. 6cest lucru nu nseamn c dimensiunea structurii este egal cu suma dimensiunilor membrilor ei deoarece din cerin+e de aliniere a unor membri se pot genera goluri ntr2o structur. @n sfr#it* cnd o func+ie returnea3 un tip complicat #i are o list complicat de argumente* ca n4 struct ,e9 +(inar9(char +word, struct ,e9 ta(, int n) func+ia poate fi mai greu 1i3ibil #i detectabil cu un editor de te-te. $in acest moti1* se poate opta #i pentru urmtoarea form4 struct ,e9 +(inar9(word,ta(,n) char +word; struct ,e9 ta(; int n; unde nainte de acolada de desc"idere se preci3ea3 tipul fiecrui parametru. 6lege+i forma care 1 con1ine #i care 1i se pare mai sugesti1.

17.). ,tructuri auto-re#erite


: considerm problema mai general* a numrului apari+iilor tuturor cu1intelor dintr2un te-t de intrare. $eoarece lista cu1intelor nu este cunoscut dinainte* n2o putem sorta folosind algoritmul de cutare binar* ca n paragraful precedent. &u putem utili3a nici o
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

777

cutare liniar pentru fiecare cu1nt* pe msura apari+iei lui pentru a 1edea dac a mai fost pre3ent sau nu* pentru c timpul de e-ecu+ie al programelor ar cre#te ptratic cu numrul cu1intelor de la intrare. ,n mod de a organi3a datele pentru a lucra eficient cu o list de cu1inte arbitrare este de a pstra mul+imea de cu1inte* tot timpul sortat* plasnd fiecare nou cu1nt din intrare pe o po3i+ie corespun3toare* relati1 la intrrile anterioare. $ac am reali3a acest lucru prin deplasarea cu1intelor ntr2un masi1 liniar* programul ar dura* de asemenea* foarte mult. $e aceea* pentru re3ol1area eficient a acestei probleme 1om folosi o structur de date numit arbore binar. Fiecare nod al arborelui 1a repre3enta un cu1nt distinct din intrare #i 1a con+ine urmtoarea informa+ie4 2 un pointer la cu1nt; 2 un contor pentru numrul de apari+ii; 2 un pointer la descendentul stng al cu1ntului; 2 un pointer la descendentul drept al cu1ntului. &ici un nod al arborelui nu 1a a1ea mai mult dect doi descenden+i dar poate a1ea un descendent sau c"iar nici unul. 6rborele se construie#te astfel nct pentru orice nod* sub2 arborele stng al su con+ine numai cu1intele care snt mai mici dect cu1ntul din nod* iar sub2arborele drept con+ine numai cu1inte* care snt mai mari dect cu1ntul din nod* compararea fcndu2se din punct de 1edere le-icografic. 0entru a #ti dac un cu1nt nou din intrare e-ist deja n arbore se porne#te de la nodul rdcin #i se compar noul cu1nt cu cu1ntul memorat n nodul rdcin. $ac ele coincid se incrementea3 contorul de numrare a apari+iilor pentru nodul rdcin #i se 1a citi un nou cu1nt din intrare. $ac noul cu1nt din intrare este mai mic dect cu1ntul memorat n nodul rdcin* cutarea continu cu descendentul stng* altfel se in1estig"ea3 descendentul drept. $ac nu e-ist nici un descendent pe direc+ia cerut* noul cu1nt nu e-ist n arbore #i 1a fi inserat pe po3i+ia descendentului corespun3tor. :e obser1 c acest proces de cutare este recursi1* deoarece cutarea din fiecare nod utili3ea3 o cutare ntr2unul dintre descenden+ii si.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77G

0rin urmare se impune de la sine ca rutinele de inserare n arbore #i de imprimare s fie recursi1e. Re1enind la descrierea unui nod* el apare ca fiind o structur cu patru componente4 struct tnode { =W nodul de ba3 W= char +word; =W pointer la cu1nt W= int count; =W numrtor de apari+ii W= struct tnode +left; =W descendent stng W= struct tnode +ri7ht; =W descendent drept W= ; 6ceast declara+ie recursi1 a unui nod este perfect legal* deoarece o structur nu poate con+ine ca #i component o intrare a ei ns#i dar poate con+ine un pointer la o structur de acela#i #ablon cu ea. $eclara+ia4 struct tnode +left; declar pe left ca fiind un pointer la structur 9nod< #i nu o structur ns#i. @n program 1om folosi rutinele 7etword* pentru citirea unui cu1nt din intrare* alloc pentru re3er1area de spa+iu necesar memorrii unui cu1nt #i alte cte1a rutine pe care le cunoa#tem deja. Rutina principal main cite#te prin intermediul rutinei get'ord un cu1nt* #i l plasea3 n arbore prin rutina tree. #define B<;XSVE .0 main() { =W contori3are apari+ii cu1inte W= struct tnode +root, +tree(); char word)B<;XSVE*; int t; root " A?>>; while ((t"7etword(word,B<;XSVE))&"@S=) if (t"">@RR@V) root " tree(root,word); treeprint(root);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77H

Rutina main gestionea3 fiecare cu1nt din intrare ncepnd cu cel mai nalt ni1el al arborelui 9rdcina<. La fiecare pas* cu1ntul din intrare este comparat cu cu1ntul asociat rdcinii #i este apoi transmis n jos* fie descendentului stng* fie celui drept* printr2un apel recursi1 la rutina tree. @n acest proces* cu1ntul fie e-ist deja* unde1a n arbore* ca3 n care contorul lui de numrare a apari+iilor se incrementea3* fie cutarea continu pn la ntlnirea unui pointer A?>>* ca3 n care nodul trebuie creat #i adugat arborelui. Cnd se creea3 un nod nou* rutina tree returnea3 un pointer la el* care apoi este introdus n nodul de origine 9adic n nodul al crui descendent este noul nod< n cmpul left sau ri7ht dup cum noul cu1nt este mai mic sau mai mare fa+ de cu1ntul origine. Rutina tree* care returnea3 un pointer la o structur de #ablon tnode are urmtorul cod4 struct tnode +tree(struct tnode +p, char +w) { =W introduce cu1ntul ' n nodul p W= struct tnode +talloc(int n); char +strsa-(char +s); int cond; if (p""A?>>) { =W a sosit un nou cu1nt W= p " talloc(); =W creea3 un nod nou W= p6>word " strsa-(w); p6>count " '; p6>left " p6>ri7ht " A?>>; else if ((cond"strcmp(w,p6>word))""0) p6>count%%; else if (cond<0) =W noul cu1nt mai mic W= p6>left " tree(p6>left,w); else =W noul cu1nt mai mare W= p6>ri7ht " tree(p6>ri7ht,w); return p;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

780

%emoria pentru noul nod se aloc de ctre rutina talloc* care este o adaptare a rutinei alloc* pe care am 13ut2o deja. Ka returnea3 un pointer la un spa+iu liber* n care se poate nscrie noul nod al arborelui. Com discuta rutina talloc mai tr3iu. &oul cu1nt se copia3 n acest spa+iu cu ajutorul rutinei strsa-* care returnea3 un pointer la nceputul cu1ntului* contorul de apari+ii se ini+iali3ea3 la 7 #i pointerii ctre cei doi descenden+i se fac A?>>. 6ceast parte de cod se e-ecut numai cnd se adaug un nou nod. Rutina treeprint tipre#te arborele astfel nct pentru fiecare nod se imprim sub2arborele lui stng* adic toate cu1intele mai mici dect cu1ntul curent* apoi cu1ntul curent #i la sfr#it sub2arborele drept* adic toate cu1intele mai mari dect cu1ntul curent. Rutina treeprint este una din cele mai tipice rutine recursi1e. treeprint(struct tnode +p) { =W tipre#te arborele p recursi1 W= if (p&"A?>>) { treeprint(p6>left); printf("#1d #s\n",p6>count,p6>word); treeprint(p6>ri7ht);

Kste important de re+inut faptul c n algoritmul de cutare n arbore* pentru a ajunge la un anumit nod* se parcurg toate nodurile precedente* pe ramura respecti1 9stng sau dreapt<* ncepnd ntotdeauna cu nodul rdcin. $up fiecare ie#ire din rutina tree* din cau3a recursi1it+ii* se parcurge acela#i drum* de data aceasta de la nodul gsit spre rdcina arborelui* refcndu2se to+i pointerii drumului parcurs. $ac considera+i ca nu a+i n+eles suficient de bine recursi1itatea* desena+i21 un arbore #i imprima+i2l cu ajutorul rutinei treeprint* a1nd grij s memora+i fiecare ie#ire din tree #i treeprint. D obser1a+ie legat de acest e-emplu4 dac arborele este nebalansate* adic cu1intele nu sosesc n ordine aleatoare din punct
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

787

de 1edere le-icografic* atunci timpul de e-ecu+ie al programului poate de1eni foarte mare. Ca3ul limit n acest sens este acela n care cu1intele de la intrare snt deja n ordine* 9cresctoare sau descresctoare<* ca3 n care programul nostru simulea3 o cutare liniar ntr2un mod destul de costisitor. : ne oprim pu+in asupra alocrii de memorie. Cu toate c se aloc diferite tipuri de obiecte* este de preferat s e-iste un singur alocator de memorie ntr2un program. Relati1 la acest alocator de memorie se pun doua probleme4 n primul rnd cum poate satisface el condi+iile de aliniere ale obiectelor de un anumit tip 9de e-emplu ntregii trebuie aloca+i la adrese pare<; n al doilea rnd cum se poate declara c alocatorul returnea3 pointeri la tipuri diferite de obiecte. Cerin+ele de aliniere pot fi n general re3ol1ate cu u#urin+ pe seama unui spa+iu care se pierde* dar care este nesemnificati1 ca dimensiune. $e e-emplu* alocatorul alloc returnea3 totdeauna un pointer la o adres par. @n ca3ul n care cererea de alocare poate fi satisfcut #i de o adres impar 9pentru #iruri de caractere* de e-emplu< se pierde un caracter. @n ceea ce pri1e#te declararea tipului alocatorului alloc 9adic a tipului de obiect pe care l indic pointerul returnat de alloc<* un foarte bun procedeu n limbajul C este de a declara c func+ia alloc returnea3 un pointer la c"ar #i apoi s con1ertim e-plicit acest pointer la tipul dorit printr2un cast. 6stfel dac p este declarat n forma4 char +p; atunci4 (struct tnode +)p; con1erte#te pe p dintr2un pointer la char ntr2un pointer la o structur de #ablon tnode* dac el apare ntr2o e-presie. bi atunci* o 1ersiune a alocatorului talloc poate fi urmtoarea4 struct tnode +talloc() { char +alloc(); return (struct tnode +) alloc (si:eof(struct tnode));
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

788

17.+. Cutare &n tabele


D alt problem legat de definirea #i utili3area structurilor este cutarea n tabele. Cnd se ntlne#te de e-emplu* o linie de forma4 #define W@M ' simbolul W@M #i te-tul de substitu+ie 7 se memorea3 ntr2o tabel. %ai tr3iu* ori de cte ori te-tul W@M 1a aprea n instruc+iuni* el se 1a nlocui cu constanta 7. Crearea #i gestionarea tabelelor de simboluri este o problem de ba3 n procesul de compilare. K-ist dou rutine principale care gestionea3 simbolurile #i te-tele lor de substitu+ie. 0rima* install(s,t) nregistrea3 simbolul s #i te-tul de substitu+ie t ntr2o tabel* s #i t fiind #iruri de caractere. 6 doua* loo,up(s) caut #irul s n tabel #i returnea3 fie un pointer la locul unde a fost gsit* fie A?>> dac #irul s nu figurea3 n tabel. 6lgoritmul folosit pentru crearea #i gestionarea tabelei de simboluri este o cutare pe ba3 de "as"ing. Fiecrui simbol i se calculea3 un cod "as" astfel4 se adun codurile 6:C;; ale caracterelor simbolului #i se ia restul pro1enit din mpr+irea numrului ob+inut din adunare #i dimensiunea tabelului. 6stfel* fiecrui simbol i se asocia3 un cod "as" H care 1erific rela+ia4 0<"H<08'00 9n "e-a3ecimal< Codul "as" astfel ob+inut 1a fi folosit apoi ca un indice ntr2o tabel de pointeri. ,n element al acestei tabele 9masi1< indic nceputul unui lan+ de blocuri care descriu simboluri cu acela#i cod "as". $ac un element al tabelei este A?>> nseamn c nici un simbol nu are 1aloarea respecti1 de "as"ing. ,n bloc dintr2un lan+ indicat de un element al tabelei este o structur care con+ine un pointer la simbol* un pointer la te-tul de substitu+ie #i un pointer la urmtorul bloc din lan+. ,n pointer A?>> la urmtorul bloc din lan+ indic sfr#itul lan+ului. bablonul unei structuri 9nod< este urmtorul4 struct nlist { char +name; char +def;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78?

struct nlist +ne8t;= W urmtoarea intrare n lan+ W= ; /abelul de pointeri care indic nceputurile lan+ului de blocuri ce descriu simboluri de acela#i cod "as" este4 #define H<MHMJT@ 08'00 static struct nlist +hashta()H<MHMJT@*; 6lgoritmul de "as"ing pe care2l pre3entm nu este cel mai bun posibil* dar are meritul de a fi e-trem de simplu4 hash(char +s) { =W formea3 1aloarea "as" pentru #irul s W= int hash-al; for (hash-al"0; +s&"!\0!;) hash-al %" +s%%; return hash-al # H<MHMJT@; 6lgoritmul de "as"ing produce un indice n masi1ul de pointeri hashta(. @n procesul de cutare a unui simbol* dac el e-ist* el trebuie s fie n lan+ul de blocuri care ncepe la adresa con+inut de elementul din hashta( cu indicele respecti1. Cutarea n tabela de simboluri hashta( se reali3ea3 cu func+ia loo,up. $ac simbolul cutat este pre3ent unde1a n lan+* func+ia returnea3 un pointer la el; altfel returnea3 A?>>. struct nlist +loo,up(char +s) { =W caut #irul s n hashta( W= struct nlist +np; for (np"hashta()hash(s)*; np&"A?>>; np"np6>ne8t) if (strcmp(s,np6>name)""0) return np; =W s2a gsit s W= return A?>>; =W nu s2a gsit s W=

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78A

Rutina install folose#te func+ia loo,up pentru a determina dac simbolul nou care trebuie introdus n lan+ este deja pre3ent sau nu. $ac mai e-ist o defini+ie anterioar pentru acest simbol* ea trebuie nlocuit cu defini+ia nou. 6ltfel* se creea3 o intrare nou pentru acest simbol* care se introduce la nceputul lan+ului. Func+ia install returnea3 A?>>* dac din anumite moti1e nu e-ist suficient spa+iu pentru crearea unui bloc unu. struct nlist +install(char +name, char +def) { =W scrie 9nume* def< n hta( W= struct nlist +np, +loo,up(); char +strsa-(), +alloc(); int hash-al; if ((np"loo,up(name))""A?>>) { =W nu s2a gsit W= np " (struct nlist+)alloc(si:eof(+np)); if (np""A?>>) return A?>>; =W nu e-ist spa+iu W= if ((np6>name"strsa-(name))""A?>>) return A?>>; hash-al " hash(np6>name); np6>ne8t " hashta()hash-al*; hashta()hash-al* " np; else =W nodul e-ist deja W= free(np6>def); =W eliberea3 defini+ia 1ec"e W= if ((np6>def"strsa-(def))""A?>>) return A?>>; return np; $eoarece apelurile la func+iile alloc #i free pot aprea n orice ordine #i deoarece alinierea contea3* 1ersiunea simpl a func+iei alloc* pre3entat n capitolul H nu este adec1at aici. @n biblioteca standard e-ist func+ii de alocare fr restric+ii* care se apelea3 implicit sau e-plicit de ctre utili3ator dintr2un program scris n C pentru a ob+ine spa+iul de memorie necesar. $eoarece #i alte ac+iuni dintr2un program pot cere spa+iu de memorie ntr2o
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78B

manier asincron* spa+iul de memorie gestionat de func+ia alloc poate s fie necontiguu. 6stfel* spa+iul liber de memorie este pstrat sub forma unui lan+ de blocuri libere* fiecare bloc con+innd o dimensiune* un pointer la urmtorul bloc #i spa+iul liber propriu23is. Blocurile snt pstrate n ordinea cresctoare a adreselor iar* ultimul bloc* de adresa cea mai mare* indic primul bloc* prin pointerul lui la blocul urmtor din lan+* astfel nct lan+ul este circular. Cnd se lansea3 o cerere* se e-aminea3 lista spa+iului liber* pn se gse#te un bloc suficient de mare pentru cererea respecti1. $ac blocul are e-act dimensiunea cerut* el se eliberea3 din lan+ul blocurilor libere #i este returnat utili3atorului. $ac blocul este mai mare se descompune* astfel nct partea cerut se transmite utili3atorului* iar partea rmas se introduce napoi n lista de spa+iu liber. $ac nu se gse#te un bloc suficient de mare pentru cererea lansat se caut un alt bloc de memorie. Kliberarea unei 3one de memorie prin intermediul rutinei free cau3ea3* de asemenea* o cutare n lista de spa+iu liber* pentru a gsi locul corespun3tor de inserare a blocului de memorie eliberat. $ac blocul de memorie eliberat este adiacent cu un bloc din lista de spa+iu liber la orice parte a sa* el este alipit la acel bloc* crendu2se un bloc mai mare* astfel ca memoria s nu de1in prea fragmentat. $eterminarea adiacen+ei este u#urat de faptul c lista de spa+iu liber se pstrea3 n ordinea cresctoare a adreselor de memorie. K-emplul de utili3are a acestor func+ii ini+iali3ea3 elementele masi1ului hashta( cu A?>>. @n continuare se a#teapt de la tastatur introducerea unui nume #i a unei defini+ii pentru acest nume. $ac numele introdus nu e-ist n lista hashta( atunci se afi#ea3 un mesaj corespun3tor* altfel se afi#ea3 1ec"ea defini+ie care este apoi nlocuit de noua defini+ie introdus. main() { char num)00*,def)00*; int i; struct nlist +np; for (i"0; i<H<MHMJT@; i%%) hashta()i* " A?>>;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78E

do { 7etword(num); 7etword(def); if ((np"loo,up(num))""A?>>) printf("Aew name\n"); else printf("Sld definitionP #s\n", np6>def); install(num,def); while (');

17.4. C&mpuri
,n cmp se define#te ca fiind o mul+ime de bi+i consecuti1i dintr2 un cu1nt sau ntreg. 6dic din moti1e de economie a spa+iului de memorie* este util mpac"etarea unor obiecte ntr2un singur cu1nt ma#in. ,n ca3 frec1ent de acest tip este utili3area unui set de flaguri* fiecare pe un bit* pentru tabela de simboluri a unui compilator. Fiecare simbol dintr2un program are anumite informa+ii asociate lui* cum snt de e-emplu* clasa de memorie* tipul* dac este sau nu cu1nt c"eie #.a.m.d. Cel mai compact mod de a codifica aceste informa+ii este folosirea unui set de flaguri* de cte un bit* ntr2un singur ntreg sau caracter. %odul cel mai u3ual pentru a face acest lucru este de a defini un set de m#ti* fiecare masc fiind corespun3toare po3i+iei bitului m interiorul caracterului sau cu1ntului. $e e-emplu4 #define N@WXSVE 0' #define @;R@VA<> 0. #define MR<RJD 0/ definesc m#tile N@WXSVE* @;R@VA<> #i MR<RJD care se refer la bi+ii 0* 7 #i respecti1 8 din caracter sau cu1nt. 6tunci accesarea acestor bi+i se reali3ea3 cu ajutorul opera+iilor de deplasare* mascare #i complementare* descri#i ntr2un capitol anterior. &umerele trebuie s fie puteri ale lui 8. K-presii de forma4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

787

fla7s H " @;R@VA<> H MR<RJD; apar frec1ent #i ele setea3 bi+ii 7 #i 8 din caracterul sau ntregul fla7s 9n e-emplul nostru< n timp ce e-presia4 fla7s $" (@;R@VA<> H MR<RJD); selectea3 bi+ii 7 #i 8 din flags. K-presia4 if (fla7s $ (@;R@VA<> H MR<RJD)) ... este ade1rat cnd cel pu+in unul din bi+ii 7 sau 8 din flags este unu. K-presia4 if (&(fla7s $ (@;R@VA<> H MR<RJD))) ... este ade1rat cnd bi+ii 7 #i 8 din flags snt ambii 3ero. Limbajul C ofer aceste e-presii* ca o alternati1* pentru posibilitatea de a defini #i de a accesa bi+ii dintr2un cu1nt* n mod direct* folosind operatorii logici pe bi+i. :inta-a defini+iei cmpului #i a accesului la el se ba3ea3 pe structuri. $e e-emplu construc+iile #define din e-emplul de mai sus pot fi nlocuite prin definirea a trei cmpuri4 struct { unsi7ned isU,e9wordP '; unsi7ned isUe8ternalP'; unsi7ned isUstaticP '; fla7s; 6ceast construc+ie define#te 1ariabila fla7s care con+ine ? cmpuri* fiecare de cte un bit. &umrul care urmea3 dup a Pa repre3int lungimea cmpului n bi+i. Cmpurile snt declarate unsi7ned pentru a sublinia c ele snt cantit+i fr semn. 0entru a ne referi la un cmp indi1idual din 1ariabila fla7s folosim o nota+ie similar cu nota+ia folosit pentru membrii structurilor. fla7s.isU,e9word fla7s.isUstatic

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78G

Cmpurile se comport ca ni#te ntregi mici fr semn #i pot participa n e-presii aritmetice ca orice al+i ntregi. 6stfel* e-presiile anterioare pot fi scrise mai natural sub forma urmtoare4 fla7s.isUe8tern " fla7s.isUstatic " '; pentru setarea bi+ilor 7 #i 8 din 1ariabila fla7s* fla7s.isUe8tern " fla7s.isUstatic " 0; pentru #tergerea bi+ilor* iar4 if (fla7s.isUe8tern""0 $$ fla7s.isUstatic""0) pentru testarea lor. ,n cmp nu trebuie s dep#easc limitele unui cu1nt. @n ca3 contrar* cmpul se alinia3 la limita urmtorului cu1nt. Cmpurile nu necesit s fie denumite. ,n cmp fr nume* descris numai prin caracterul aPa #i lungimea lui n bi+i este folosit pentru a re3er1a spa+iu n 1ederea alinierii urmtorului cmp. Lungimea 3ero a unui cmp poate fi folosit pentru for+area alinierii urmtorului cmp la limita unui nou cu1nt* el fiind presupus a con+ine tot cmpuri #i nu un membru obi#nuit al structuri* deoarece n acest ultim ca3* alinierea se face n mod automat. &ici un cmp nu poate fi mai lung dect un cu1nt. Cmpurile se atribuie de la dreapta la stnga. Cmpurile nu pot constitui masi1e* nu au adrese* astfel nct operatorul '$' nu se poate aplica asupra lor.

17.5. ;euniuni
D reuniune este o 1ariabil care poate con+ine* la momente diferite* obiecte de diferite tipuri #i dimensiuni; compilatorul este cel care +ine e1iden+a dimensiunilor #i aliniamentului. Reuniunile ofer posibilitatea ca mai multe tipuri diferite de date s fie tratate ntr2o singur 3on de memorie* fr a folosi n program 1reo informa+ie dependent de ma#in. : relum e-emplul tabelei de simboluri a unui compilator* presupunnd c constantele pot fi de tip int* float sau #iruri de caractere.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

78H

Caloarea unei constante particulare trebuie memorat ntr2o 1ariabil de tip corespun3tor* cu toate c este mai con1enabil* pentru gestiunea tabelei de simboluri* ca 1aloarea s fie memorat n aceea#i 3on de memorie* indiferent de tipul ei #i s ocupe aceea#i cantitate de memorie. 6cesta este scopul unei reuniuni4 de a furni3a o singur 1ariabil care s poat con+ine oricare dintre 1alorile unor tipuri de date. Ca #i n ca3ul cmpurilor* sinta-a defini+iei #i accesului la o reuniune se ba3ea3 pe structuri. Fie defini+ia4 union uUta7. { int i-al; float f-al; char +p-al; u-al; Cariabila u-al 1a fi suficient de mare ca s poat pstra pe cea mai mare dintre cele trei tipuri de componente. Dricare dintre tipurile de mai sus poate fi atribuit 1ariabilei u-al #i apoi folosit n e-presii n mod corespun3tor* adic tipul n u-al este tipul ultim atribuit. ,tili3atorul este cel care +ine e1iden+a tipului curent memorat ntr2o reuniune. :intactic* membrii unei reuniuni snt accesibili printr2o construc+ie de forma4 nume-reuniune. membru sau pointer-la-reuniune6>membru $ac 1ariabila ut9pe este utili3at pentru a +ine e1iden+a tipului curent memorat n u-al* atunci fie urmtorul cod4 if (ut9pe""JAR) printf ("#d\n",u-al.i-al); else if (ut9pe"" =>S<R) printf("#f\n",u-al.f-al); else if (ut9pe""MRVJAY) printf("#s\n",u-al.p-al); else printf("tip incorect #d in ut9pe\n", ut9pe);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?0

Reuniunile pot aprea n structuri #i masi1e #i in1ers. :inta-a pentru accesarea unui membru al unei reuniuni* dintr2o structur* sau in1ers este identic cu cea pentru structurile imbricate. 0e e-emplu* n masi1ul de structuri s9mta()AMWB* definit de4 struct { char + name; int fla7s; int ut9pe; union { int i-al; float f-al; char +p-al; u-al; s9mta()AMWB*; 1ariabila i-al se refer prin4 s9mta()i*.u-al.i-al iar primul caracter al #irului pointat de p-al prin4 +s9mta()i*.u-al.p-al $e fapt* o reuniune este o structur n care to+i membrii au deplasamentul 3ero* structura fiind suficient de mare pentru a putea pstra pe cel mai mare membru. 6linierea este corespun3toare pentru toate tipurile reuniunii. Ca #i la structuri* singurele opera+ii permise cu reuniuni snt accesul la un membru al reuniunii #i considerarea adresei ei. Reuniunile nu pot fi atribuite* transmise la func+ii sau returnate de ctre acestea. 0ointerii la reuniuni pot fi folosi+i n mod similar cu pointerii la structuri.

17.6. 8eclaraii de structuri> reuniuni i c&mpuri


$eoarece specificatorii de structuri* reuniuni #i cmpuri au aceea#i form 1om pre3enta sinta-a lor general n acest paragraf. &pecificator-structur-sau-reuniune4 struct-sau-union { lista-declaraiilor
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?7

struct-sau-union identificator { lista-declaraiilor struct-sau-union identificator &truct-sau-union4 struct union Lista2declara+iilor este o sec1en+ de declara+ii pentru membrii structurii sau reuniunii. !ista-declaraiilor4 declaraie-structur declaraie-structur, lista-declaraiilor (eclaraie-structur4 specificator-tip, lista-declarator; !ista-declarator4 declarator-structur declarator-structur, lista-declarator @n mod obi#nuit* un declarator2structur este c"iar un declarator pentru un membru al structurii sau reuniunii. ,n membru al structurii poate fi constituit dintr2un numr specificat de bi+i* ca3 n care a1em de2a face cu un cmp. Lungimea lui se separ de nume prin caracterul aPa 6tunci4 (eclarator-structur4 declarator declarator P expresie-constant P expresie-constant @ntr2o structur fiecare membru care nu este un cmp ncepe la o adres corespun3toare tipului su. 6stfel ntr2o structur pot e-ista 3one fr nume neutili3ate* re3ultate din moti1e de aliniere. Limbajul C nu introduce restric+ii pri1ind tipurile obiectelor care pot fi declarate cmpuri. ,n specificator2structur2sau2reuniune de forma a doua declar un identificator ca fiind etic"eta 9marcajul< structurii sau reuniunii. 6tunci o declara+ie ulterioar poate folosi forma a treia a unui specificator2structur2sau2reuniune.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?8

Ktic"etele de structuri permit definirea structurilor auto2referite; de asemenea permit ca partea de declara+ie a corpului structurii s fie dat o singur dat #i folosit de mai multe ori. Kste inter3is declararea recursi1 a unei structuri sau reuniuni* dar o structur sau o reuniune poate con+ine un pointer la ea. $ou structuri pot partaja o sec1en+ ini+ial comun de membri; adic acela#i membru poate aprea n dou structuri diferite dac el are acela#i tip n ambele structuri #i dac to+i membri preceden+i lui snt identici n cele dou structuri.

17.17. Typedef
Limbajul C ofer o facilitate numit t)pedef pentru a crea noi nume de tipuri de date. :pecificatorul de tip t)pedef2nume are sinta-a4 typedef-nume4 declarator @ntr2o declara+ie implicnd t9pedef fiecare identificator care apare ca parte a unui declarator de1ine sintactic ec"i1alent cu cu1ntul c"eie re3er1at pentru tipul asociat cu identificatorul. $e e-emplu* declara+ia4 t9pedef int >@AYRH; l face pe >@AYRH sinonim cu int. /ipul >@AYRH poate fi folosit ulterior n declara+ii n acela#i mod ca #i tipul int. >@AYRH len, ma8len; >@AYRH +len7th)*; @n mod similar* declara+ia4 t9pedef char +MRVJAY; l face pe MRVJAY sinonim cu char+* adic pointer la caracter* care apoi poate fi utili3at n declara+ii de tipul4 MRVJAY p, lineptr)>JA@M*, alloc(); :e obser1 c tipul care se declar prin t9pedef apare pe po3i+ia numelui de 1ariabil nu imediat dup cu1ntul re3er1at t9pedef. :intactic t9pedef este sinonim cu clasele de memorie
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7??

e8tern* static etc* dar nu re3er1 memorie pentru 1ariabilele respecti1e. Ca un e-emplu mai complicat s relum declara+ia unui nod al unui arbore* de data aceasta folosind t9pedef pentru a crea un nou nume pentru un tip structur 91e3i sec+iunea 70.B<. t9pedef struct tnode { char +word; int count; struct tnode +left; struct tnode +ri7ht; RV@@ASE@, +RV@@ZRV; =W pointer la te-t W= =W numr apari+ii W= =W descendent stng W= =W descendent drept W=

6ceast declara+ie creea3 dou nume noi de tipuri* numite RV@@ASE@* care este o structur #i RV@@ZRV* care este un pointer la o structur. 6tunci rutina talloc poate fi scris sub forma4 RV@@ZRV talloc() { char +alloc(); return (RV@@ZRV)alloc(si:eof(RV@@ASE@))); /rebuie subliniat faptul c declara+ia t9pedef nu creea3 noi tipuri n nici un ca3; ea adaug doar sinonime pentru anumite tipuri de date* deja e-istente. Cariabilele declarate n acest fel au e-act acelea#i propriet+i ca #i cele declarate e-plicit. $e fapt* t9pedef se aseamn cu #define* cu e-cep+ia faptului c n timp ce #define este tratat de preprocesor* t9pedef este tratat de ctre compilator. $e e-emplu4 t9pedef int(+Z=J)(); creea3 numele Z=J pentru pointer la o funcie care returneaz un ntre * tip care poate fi folosit ulterior ntr2un conte-t de tipul4 Z=J strcmp, numcmp, swap; n programul de sortare din capitolul H. K-ist dou moti1e principale care impun folosirea declara+iilor t9pedef. 0rimul este legat de problemele de portabilitate. Cnd se folosesc declara+ii t9pedef pentru tipuri de date care snt
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?A

dependente de ma#in* atunci pentru o compilare pe un alt sistem de calcul este necesar modificarea doar a acestor declara+ii nu #i a datelor din program. 6l doilea const n faptul c prin crearea de noi nume de tipuri se ofer posibilitatea folosirii unor nume mai sugesti1e n program* deci o mai rapid n+elegere a programului.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?B

11. Intrri ? ieiri


@ntruct limbajul C nu a fost de31oltat pentru un sistem particular de operare #i datorit faptului c s2a dorit reali3area unei portabilit+i ct mai mari* att a unui compilator C* ct #i a programelor scrise n acest limbaj* el nu posed facilit+i de intrare = ie#ire. K-ist totu#i un sistem de intrare = ie#ire 9sistemul ;=D< constituit dintr2un numr de subprograme care reali3ea3 func+ii de intrare = ie#ire pentru programe scrise n C* dar care nu fac parte din limbajul C. 6ceste subprograme se gsesc n biblioteca C. :copul acestui capitol este de a descrie cele mai utili3ate subprograme de intrare = ie#ire #i interfa+a lor cu programele scrise n limbajul C.

11.1. Intrri i ieiri standard= #iiere


:istemul ;=D ofer utili3atorului trei Sfi#iereS standard de lucru. Cu1ntul fi#ier a fost pus ntre g"ilimele* deoarece limbajul nu define#te acest tip de dat #i pentru c fi#ierele repre3int mai degrab ni#te flu-uri de intrare = ie#ire standard puse la dispo3i+ia utili3atorului. 6ceste fi#iere snt4 5 fi#ierul standard de intrare 9stdin<; 5 fi#ierul standard de ie#ire 9stdout<; 5 fi#ierul standard de afi#are a mesajelor 9 stderr<. /oate aceste trei fi#iere snt sec1en+iale #i n momentul e-ecu+iei unui program C snt implicit definite #i desc"ise. stdin #i stdout snt asociate n mod normal terminalului de la care a fost lansat programul n e-ecu+ie. :istemul ;=D permite redirectarea acestor fi#iere pe alte periferice sau nc"iderea lor dup lansarea programului. Redirectarea fi#ierului stdin se specific prin construc+ia4 <specificator-fiier n linia de comand prin care a fost lansat programul.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?E

Redirectarea fi#ierului stdout se specific prin construc+ia4 >specificator-fiier n linia de comand prin care a fost lansat programul. Redirectarea fi#ierului stdout pe un alt periferic* n scopul efecturii unei opera+ii de adugare 9append< se specific prin construc+ia 4 >>specificator-fiier stderr este ntotdeauna asociat terminalului de la care a fost lansat programul n e-ecu+ie #i nu poate fi redirectat. 0entru a se putea face o referire la aceste fi#iere orice program C trebuie s con+in fi#ierul stdio.h* care se include printr2o linie de forma4 #include <stdio.h> dac acest fi#ier se afl n biblioteca standard. 0entru claritatea #i li3ibilitatea programelor scrise n C* ct #i pentru crearea unei imagini sugesti1e asupra lucrului cu fi#iere* n fi#ierul de defini+ii standard stdio.h s2a definit un nou nume de tip de dat #i anume =J>@ care este o structur. 0entru a referi un fi#ier* este necesar o declara+ie de forma4 =J>@ +fp; unde fp 1a fi numele de dat cu care se 1a referi fi#ierul n orice opera+ie de intrare = ie#ire asociat. ;at cte1a informa+ii pstrate de structura =J>@4 5 un identificator de fi#ier pe care sistemul de operare l asocia3 flu-ului pe durata prelucrrii; acesta poate fi aflat cu ajutorul func+iei fileno; 5 adresele 3onelor tampon asociate; po3i+ia curent n aceste 3one; 5 indicatorii de sfr#it de fi#ier #i de eroare; 5 alte informa+ii.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?7

11.2. :ccesul la #iiere= desc%idere i &nc%idere


&ume fopen 2 desc"ide un flu$eclara+ie =J>@ +fopen(const char +path, const char +mode); $escriere Func+ia fopen desc"ide fi#ierul al crui nume este un #ir indicat de path #i i asocia3 un flu-. 6rgumentul mode indic un #ir care ncepe cu una din sec1en+ele urmtoare4 r desc"ide un fi#ier pentru citire; r+ desc"ide pentru citire #i scriere; w trunc"ia3 fi#ierul la lungime 3ero sau creea3 un fi#ier pentru scriere; w+ desc"ide pentru adugare la sfr#it* n citire #i scriere; fi#ierul este creat dac nu e-ist* altfel este trunc"iat; a desc"ide pentru adugare la sfr#it* n scriere; fi#ierul este creat dac nu e-ist; a+ desc"ide pentru adugare la sfr#it* n citire #i scriere; fi#ierul este creat dac nu e-ist; $up desc"idere* n primele patru ca3uri indicatorul po3i+iei n flu- este la nceputul fi#ierului* n ultimele dou la sfr#itul acestuia. birul mode include de asemenea litera b 9desc"ide un fi#ier binar< sau t 9desc"ide un fi#ier te-t< fie pe ultima po3i+ie fie pe cea din mijloc. Dpera+iile de citire #i scriere pot alterna n ca3ul flu-urilor read = 'rite n orice ordine. : re+inem c standardul 6&:; C cere s e-iste o func+ie de po3i+ionare ntre o opera+ie de intrare #i una de ie#ire* sau ntre o opera+ie de ie#ire #i una de intrare* cu e-cep+ia ca3ului cnd o opera+ie de citire detectea3 sfr#itul de fi#ier. 6ceast opera+ie poate
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?G

fi inefecti1 2 cum ar fi fsee,(flu8, 0>, M@@NUD?V) apelat cu scop de sincroni3are. Calori returnate @n ca3 de succes se returnea3 un pointer de tip =J>@. @n ca3 de eroare se returnea3 A?>> #i 1ariabila global errno indic codul erorii.

&ume fclose 2 nc"ide un flu$eclara+ie int fclose( =J>@ +flu8); $escriere Func+ia fclose nc"ide fi#ierul asociat flu-ului flu8. $ac flu8 a fost desc"is pentru ie#ire* orice date aflate n 3one tampon snt scrise n fi#ier n prealabil cu un apel fflush. Calori returnate @n ca3 de succes se returnea3 0. @n ca3 de eroare se returnea3 @S= #i 1ariabila global errno indic codul erorii.

&ume tmpfile 2 creea3 un fi#ier temporar


$eclara+ie =J>@ +tmpfile(); $escriere Func+ia tmpfile generea3 un nume unic de fi#ier temporar. 6cesta este desc"is n mod binar pentru scriere = citire 9 "wb+"<. Fi#ierul 1a fi #ters automat la nc"idere sau la terminarea programului. Caloare returnat Func+ia returnea3 un descriptor de flu- n ca3 de succes* sau A?>> dac nu poate fi generat un nume unic de fi#ier sau dac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7?H

fi#ierul nu poate fi desc"is. @n ca3 de eroare 1ariabila global errno indic codul erorii.

&ume fflush 2 for+ea3 scrierea n flu$eclara+ie int fflush(=J>@ +flu8); $escriere Func+ia fflush for+ea3 o scriere a tuturor datelor aflate n 3one tampon ale flu-ului flu8. Flu-ul rmne desc"is. Calori returnate @n ca3 de succes se returnea3 0. @n ca3 de eroare se returnea3 @S= #i 1ariabila global errno indic codul erorii.

&ume fseek* ftell* rewind 2 repo3i+ionea3 un flu$eclara+ie int fsee,(=J>@ +flu8, lon7 offset, int reper); lon7 ftell(=J>@ +flu8); -oid rewind(=J>@ +flu8); $escriere Func+ia fsee, setea3 indicatorul de po3i+ie pentru fi#ierul asociat flu-ului flu8. &oua po3i+ie* dat n octe+i* se ob+ine adunnd offset octe+i la po3i+ia specificat de reper. $ac reper este M@@NUM@R* M@@NUD?V* sau M@@NU@AE* offset este relati1 la nceputul fi#ierului* po3i+ia curent a indicatorului* respecti1 sfr#itul fi#ierului. Func+ia fsee, #terge indicatorul de sfr#it de fi#ier. Func+ia ftell ob+ine 1aloarea curent a indicatorului de po3i+ie pentru fi#ierul asociat flu-ului flu8.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A0

Func+ia rewind po3i+ionea3 indicatorul de po3i+ie pentru fi#ierul asociat flu-ului flu8 la nceputul fi#ierului. Kste ec"i1alent cu4 (-oid)fsee,(flu8, 0>, M@@NUM@R) cu completarea c func+ia rewind #terge #i indicatorul de eroare al flu-ului. Calori returnate Func+ia rewind nu returnea3 nici o 1aloare. @n ca3 de succes* fsee, returnea3 0* #i ftell returnea3 offset2ul curent. @n ca3 de eroare se returnea3 @S= #i 1ariabila global errno indic codul erorii.

11.3. Citire i scriere #r #ormat


&ume fgets 2 cite#te un #ir de caractere dintr2un flu- te-t
$eclara+ie char +f7ets(char +s, int si:e, =J>@ +flu8); $escriere Func+ia f7ets cel mult si:e6' caractere din flu8 #i le memorea3 n 3ona indicat de s. Citirea se opre#te la detectarea sfr#itului de fi#ier sau ne'2line. $ac se cite#te caracterul ne'2line acesta este memorat n s. $up ultimul caracter se memorea3 null. 6peluri ale acestei func+ii pot fi combinate cu orice apeluri ale altor func+ii de intrare din bibliotec 9 fscanf* de e-emplu< pentru un acela#i flu- de intrare. Calori returnate Func+ia returnea3 adresa s n ca3 de succes* sau A?>> n ca3 de eroare sau la ntlnirea sfr#itului de fi#ier dac nu s2a citit nici un caracter.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A7

&ume fputs 2 scrie un #ir de caractere ntr2un flu- te-t


$eclara+ie int fputs(const char +s, =J>@ +flu8); $escriere Func+ia fputs scrie #irul s n flu- fr caracterul terminator null. 6peluri ale acestei func+ii pot fi combinate cu orice apeluri ale altor func+ii de ie#ire din bibliotec 9 fprintf* de e-emplu< pentru un acela#i flu- de ie#ire. Calori returnate Func+ia returnea3 o 1aloare non2negati1 n ca3 de succes* sau @S= n ca3 de eroare.

&ume fread* fwrite 2 intrri = ie#iri pentru flu-uri binare


$eclara+ie unsi7ned fread(-oid +ptr, unsi7ned si:e, unsi7ned nel, =J>@ +flu8); unsi7ned fwrite(const -oid +ptr, unsi7ned si:e, unsi7ned nel, =J>@ +flu8); $escriere Func+ia fread cite#te nel elemente* fiecare a1nd mrimea si:e octe+i* din flu-ul indicat de flu8* #i le memorea3 n 3ona indicat de ptr. Func+ia fwrite scrie nel elemente* fiecare a1nd mrimea si:e octe+i* din flu-ul indicat de flu8* pe care le ia din 3ona indicat de ptr. Calori returnate Func+iile returnea3 numrul de elemente citite sau scrise cu succes 9#i nu numrul de caractere<. $ac apare o eroare sau se
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A8

ntlne#te sfr#itul de fi#ier* 1aloarea returnat este mai mic dect nel 9posibil 3ero<.

11.'. Citire cu #ormat


&ume scanf* fscanf* sscanf 2 citire cu format
$eclara+ie int scanf(const char +format, ...); int fscanf(=J>@ +flu8, const char +format, ...); int sscanf(const char +str, const char +format, ...); $escriere Familia de func+ii scanf scanea3 intrarea n concordan+ cu #irul de caractere format dup cum se descrie mai jos. 6cest format poate con+ine specificatori de con1ersie; re3ultatele unor astfel de con1ersii 9dac se efectuea3< se memorea3 prin intermediul argumentelor pointer. Func+ia scanf cite#te #irul de intrare din flu-ul standard stdin* fscanf din flu8* #i sscanf din #irul indicat de str. Fiecare argument pointer trebuie s corespund n ordine ca tip cu fiecare specificator de con1ersie 9dar a se 1edea suprimarea mai jos<. $ac argumentele nu snt suficiente comportamentul programului este impre1i3ibil. /oate con1ersiile snt introduse de caracterul %. birul format poate con+ine #i alte caractere. :pa+ii albe 9blanc* tab* sau ne'2line< din #irul format se potri1esc cu orice spa+iu alb n orice numr 9inclusi1 nici unul< din #irul de intrare. Drice alte caractere trebuie s se potri1easc e-act. :canarea se opre#te atunci cnd un caracter din #irul de intrare nu se potri1e#te cu cel din format. :canarea se opre#te de asemenea atunci cnd o con1ersie nu se mai poate efectua 9a se 1edea mai jos<.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A?

Con1ersii $up caracterul % care introduce o con1ersie poate urma un numr de caractere indicatori* dup cum urmea34 * :uprim atribuirea. Con1ersia care urmea3 se face n mod obi#nuit* dar nu se folose#te nici un argument pointer; re3ultatul con1ersiei este pur #i simplu abandonat. Con1ersia este de tip dioux sau n #i argumentul asociat este un pointer la short 9n loc de int<. Con1ersia este de tip dioux sau n #i argumentul asociat este un pointer la lon7 9n loc de int<* sau con1ersia este de tip efg #i argumentul asociat este un pointer la dou(le 9n loc de float<. Con1ersia este de tip efg #i argumentul asociat este un pointer la lon7 dou(le.

h l

@n completare la ace#ti indicatori poate e-ista o mrime w ma-im op+ional pentru cmp* e-primat ca un ntreg 3ecimal* ntre caracterul % #i cel de con1ersie* #i naintea indicatorului. $ac nu este dat o mrime ma-im se folose#te mrimea implicit infinit 9cu o e-cep+ie la con1ersia de tip c<; n ca3 contrar se scanea3 cel mult un numr de w caractere n timpul con1ersiei. @nainte de a ncepe o con1ersie* majoritatea con1ersiilor ignor spa+iile albe; acestea nu snt contori3ate n mrimea cmpului. :nt disponibile urmtoarele con1ersii4 % 0otri1ire cu un caracter %. Cu alte cu1inte* %% n #irul format trebuie s se potri1easc cu un caracter %. &u se efectuea3 nici o con1ersie #i nici o atribuire. 0otri1ire cu un ntreg 3ecimal 9e1entual cu semn<; argumentul asociat trebuie s fie un pointer la int. 0otri1ire cu un ntreg 9e1entual cu semn<; argumentul asociat trebuie s fie un pointer la int. Caloarea ntreag este citit n
7AA

d i

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ba3a 7E dac ncepe cu 08 sau 0;* n ba3a G dac ncepe cu 0* #i n ba3a 70 n ca3 contrar. :nt folosite numai caracterele care corespund ba3ei respecti1e. o u x f 0otri1ire cu un ntreg octal fr semn; argumentul asociat trebuie s fie un pointer la unsi7ned. 0otri1ire cu un ntreg 3ecimal fr semn; argumentul asociat trebuie s fie un pointer la unsi7ned. 0otri1ire cu un ntreg "e-a3ecimal fr semn; argumentul asociat trebuie s fie un pointer la unsi7ned. 0otri1ire cu un numr n 1irgul mobil 9e1entual cu semn<; argumentul asociat trebuie s fie un pointer la float. 0otri1ire cu o sec1en+ de caractere diferite de spa+iu alb; argumentul asociat trebuie s fie un pointer la char* #i 3ona trebuie s fie suficient de mare pentru a putea primi toat sec1en+a #i caracterul terminator null. birul de intrare se termin la un spa+iu alb sau la atingerea mrimii ma-ime a cmpului 9prima condi+ie ntlnit<. 0otri1ire cu o sec1en+ de caractere de mrime w 9dac aceasta este specificat; prin lips se ia w=7<; argumentul asociat trebuie s fie un pointer la char* #i 3ona trebuie s fie suficient de mare pentru a putea primi toat sec1en+a 9nu se adaug terminator null<. &u se ignor ca de obicei spa+iile albe din fa+. 0entru a ignora mai nti spa+iile albe se indic un spa+iu e-plicit n format. 0otri1ire cu o sec1en+ ne1id de caractere din setul specificat de caractere acceptate; argumentul asociat trebuie s fie un pointer la char* #i 3ona trebuie s fie suficient de mare pentru a putea primi toat sec1en+a #i caracterul terminator null. &u se ignor ca de obicei spa+iile albe din fa+. birul de intrare 1a fi format din caractere aflate n 9sau care nu se afl n< setul specificat n format; setul este definit de caracterele aflate ntre [ #i . :etul
7AB

e*g Kc"i1alent cu f. s

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

e-clude acele caractere dac primul caracter dup [ este !. 0entru a include caracterul n set* acesta trebuie s fie primul caracter dup [ sau !; caracterul aflat n orice alt po3i+ie nc"ide setul. Caracterul " are #i el un rol special4 plasat ntre dou alte caractere adaug toate celelalte caractere aflate n inter1alul respecti1 la set. 0entru a include caracterul " acesta trebuie s fie ultimul caracter nainte de . $e e-emplu* "# )L*0646*" semnific setul orice caracter cu excepia * # pn la $* i ". birul se termin la apari+ia unui caracter care nu se afl 9sau* dac se preci3ea3 !* care se afl< n set sau dac se atinge mrimea ma-im specificat. p n 0otri1ire cu o 1aloare pointer 9a#a cum se afi#ea3 cu %p n printf<; argumentul asociat trebuie s fie un pointer la pointer. &u se prelucrea3 nimic din #irul de intrare; n sc"imb* numrul de caractere consumate pn la acest punct din #irul de intrare este memorat la argumentul asociat* care trebuie s fie un pointer la int.

Calori returnate Func+iile returnea3 numrul de 1alori atribuite* care poate fi mai mic dect numrul de argumente pointer* sau c"iar 3ero* n ca3ul n care apar nepotri1iri ntre format #i #irul de intrare. Qero indic faptul c* c"iar dac a1em un #ir de intrare disponibil* nu s2a efectuat nici o con1ersie 9#i atribuire<; aceast situa+ie apare atunci cnd un caracter din #irul de intrare este in1alid* cum ar fi un caracter alfabetic pentru o con1ersie %d. Caloarea @S= este returnat dac apare un eroare nainte de prima con1ersie* cum ar fi detectarea sfr#itului de fi#ier. $ac o eroare sau un sfr#it de fi#ier apare dup ce o con1ersie a nceput* se returnea3 numrul de con1ersii efectuate cu succes.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7AE

11.). ,criere cu #ormat


&ume printf* fprintf* sprintf 2 scriere cu format
$eclara+ie int printf(const char +format, ...); int fprintf(=J>@ +flu8, const char +format, ...); int sprintf(char +str, const char +format, ...); $escriere Func+iile din familia printf generea3 o ie#ire n concordan+ cu format dup cum se descrie mai jos. Func+ia printf afi#ea3 ie#irea la flu-ul standard stdout; fprintf scrie ie#irea la flu8; sprintf scrie ie#irea n #irul de caractere str. 6ceste func+ii generea3 ie#irea sub controlul #irului format care specific cum se con1ertesc argumentele pentru ie#ire. birul de formatare birul format este un #ir de caractere* printre care se pot afla 3ero sau mai multe directi1e4 caractere obi#nuite 9diferite de %< care snt copiate a#a cum snt n flu-ul de ie#ire* #i specifica+ii de con1ersie* fiecare dintre ele re3ultnd din ncrcarea a 3ero sau mai multe argumente. Fiecare specifica+ie de con1ersie este introdus de caracterul % #i se termin cu un specificator de con1ersie. @ntre acestea pot fi 9n aceast ordine< 3ero sau mai mul+i indicatori* o mrime minim a cmpului op+ional* o preci3ie op+ional #i un modificator op+ional de lungime. 6rgumentele trebuie s corespund n ordine cu specificatorii de con1ersie. 6cestea snt folosite n ordinea dat* unde fiecare caracter * #i fiecare specificator de con1ersie solicit urmtorul argument. $ac argumentele nu snt suficiente comportamentul programului este impre1i3ibil.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7A7

Caractere indicatori Caracterul % este urmat de 3ero* unul sau mai mul+i indicatori4 % Caloarea numeric se con1erte#te n format alternati1. 0entru con1ersii de tip o* primul caracter al #irului de ie#ire este 3ero 9prin prefi-are cu 0 dac 1aloarea nu este 3ero<. 0entru con1ersii de tip x #i &* o 1aloare nenul este prefi-at cu 08 9sau 0; pentru con1ersii de tip &<. 0entru con1ersii de tip e* '* f* (* g #i )* re3ultatul 1a con+ine ntotdeauna punctul 3ecimal* c"iar dac nu apare partea frac+ionar 9n mod normal punctul 3ecimal apare n aceste con1ersii numai dac e-ist #i partea frac+ionar<. 0entru con1ersii de tip g #i ) 3erourile finale nu snt eliminate a#a cum se procedea3 n mod normal. 0entru alte con1ersii re3ultatul este nedefinit. Caloarea numeric este con1ertit cu 3erouri la stnga. 0entru con1ersii de tip d* i* o* u* x* &* e* '* f* (* g #i )* 1aloarea con1ertit este completat cu 3erouri la stnga n loc de blanc. $ac apar indicatorii # #i " mpreun* indicatorul # este ignorat. $ac pentru o con1ersie numeric 9 d* i* o* u* x* &< este dat o preci3ie* indicatorul # este ignorat. 0entru alte con1ersii re3ultatul este nedefinit. Caloarea con1ertit este aliniat la stnga 9implicit alinierea se face la dreapta<. Cu e-cep+ia con1ersiilor de tip n* 1aloarea con1ertit este completat la dreapta cu blanc* n loc s fie completat la stnga cu blanc sau 3ero. $ac apar indicatorii # #i " mpreun* indicatorul # este ignorat.

"

&p 9spa+iu< @n ca3ul unui re3ultat al unei con1ersii cu semn* naintea unui numr po3iti1 sau #ir 1id se pune un blanc. + :emnul 9% sau 6< este plasat naintea numrului generat de o con1ersie cu semn. ;mplicit semnul este folosit numai pentru numere negati1e. $ac apar indicatorii + #i &p mpreun* indicatorul &p este ignorat.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7AG

L+imea cmpului ,n #ir de cifre 3ecimale 9cu prima cifr nenul< specific o l+ime minim pentru cmp. $ac 1aloarea con1ertit are mai pu+ine caractere dect l+imea specificat* 1a fi completat cu spa+ii la stnga 9sau dreapta* dac s2a specificat aliniere la stnga<. @n locul unui numr 3ecimal se poate folosi + pentru a specifica faptul c l+imea cmpului este dat de argumentul urmtor* care trebuie s fie de tip int. D 1aloare negati1 pentru l+ime este considerat un indicator " urmat de o 1aloare po3iti1 pentru l+ime. @n nici un ca3 nu se 1a trunc"ia cmpul; dac re3ultatul con1ersiei este mai mare dect l+imea cmpului* cmpul este e-pandat pentru a con+ine re3ultatul con1ersiei. 0reci3ia 0reci3ia 9op+ional< este dat de caracterul . urmat de un #ir de cifre 3ecimale. @n locul #irului de cifre 3ecimale se poate scrie * pentru a specifica faptul c preci3ia este dat de argumentul urmtor* care trebuie s fie de tip int. $ac preci3ia este dat doar de .* sau dac preci3ia este negati1* atunci aceasta se consider 3ero. 0reci3ia d numrul minim de cifre care apar pentru con1ersii de tip d* i* o* u* x* &* numrul de cifre care apar dup punctul 3ecimal pentru con1ersii de tip e* '* f* (* numrul ma-im de cifre semnificati1e pentru con1ersii de tip g #i )* sau numrul ma-im de caractere generate pentru con1ersii de tip s. %odificator de lungime @n acest ca3 prin con1ersie ntreag n+elegem con1ersie de tip d* i* o* u* x* &. h Con1ersia ntreag care urmea3 corespunde unui argument short sau unsi7ned short* sau urmtoarea con1ersie de tip n corespunde unui argument de tip pointer la short. Con1ersia ntreag care urmea3 corespunde unui argument lon7 sau unsi7ned lon7* sau urmtoarea con1ersie de tip n corespunde unui argument de tip pointer la lon7.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7AH

,rmtoarea con1ersie de tip e* '* f* g sau ) corespunde unui argument lon7 dou(le.

:pecificator de con1ersie ,n caracter care specific tipul con1ersiei care se 1a face. :pecificatorii de con1ersie #i semnifica+ia lor snt4 d*i 6rgumentul de tip int este con1ertit la nota+ia 3ecimal cu semn. 0reci3ia* dac este dat* d numrul minim de cifre care trebuie s apar; dac 1aloarea con1ertit necesit mai pu+ine cifre* aceasta este completat la stnga cu 3erouri. 0reci3ia implicit este 7. $ac 1aloarea 0 este afi#at cu preci3ie e-plicit 0* ie#irea este 1id. o*u*x*& 6rgumentul de tip unsi7ned este con1ertit la nota+ie octal fr semn 9o<* 3ecimal fr semn 9u<* sau "e-a3ecimal fr semn 9x #i &<. Literele a(cdef se folosesc pentru con1ersii de tip x; literele <CDE@= pentru con1ersii de tip &. 0reci3ia* dac este dat* d numrul minim de cifre care trebuie s apar; dac 1aloarea con1ertit necesit mai pu+ine cifre* aceasta este completat la stnga cu 3erouri. 0reci3ia implicit este 7. $ac 1aloarea 0 este afi#at cu preci3ie e-plicit 0* ie#irea este 1id. e*' 6rgumentul de tip flotant este rotunjit #i con1ertit n stil Y6[d.dddefdd unde a1em o cifr nainte de punctul 3ecimal #i numrul de cifre dup acesta este egal cu preci3ia; dac aceasta lipse#te se consider E; dac preci3ia este 3ero* punctul 3ecimal nu apare. D con1ersie de tip ' folose#te litera @ 9n loc de e< pentru a introduce e-ponentul. K-ponentul are ntotdeauna cel pu+in dou cifre; dac 1aloarea este 3ero* e-ponentul este 00. f*( 6rgumentul de tip flotant este rotunjit #i con1ertit n nota+ie 3ecimal n stil Y6[ddd.ddd* unde numrul de cifre dup punctul 3ecimal este egal cu preci3ia specificat. $ac preci3ia lipse#te se
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7B0

consider E; dac preci3ia este e-plicit 3ero* punctul 3ecimal nu apare. $ac punctul 3ecimal apare* cel pu+in o cifr apare naintea acestuia. g*) 6rgumentul de tip flotant este con1ertit n stil f sau e 9sau ' pentru con1ersii de tip )<. 0reci3ia specific numrul de cifre semnificati1e. $ac preci3ia lipse#te se consider E; dac preci3ia este 3ero se consider 7. :tilul e este folosit dac e-ponentul re3ultat n urma con1ersiei este mai mic dect A ori mai mare sau egal cu preci3ia. Qerourile finale snt eliminate din partea frac+ionar a re3ultatului; punctul 3ecimal apare numai dac este urmat de cel pu+in o cifr. c s 6rgumentul de tip int este con1ertit la unsi7ned char #i se scrie caracterul re3ultat. 6rgumentul de tip const char + este un pointer la un #ir de caractere. Caracterele din #ir snt scrise pn la 9fr a include< caracterul terminator null; dac preci3ia este specificat* nu se scrie un numr mai mare dect cel specificat. $ac preci3ia este dat* nu e ne1oie de caracterul null; dac preci3ia nu este specificat* sau dac este mai mare dect mrimea #irului* #irul trebuie s con+in un caracter terminator null. 6rgumentul de tip pointer este scris n "e-a3ecimal; formatul este specific sistemului de calcul. &umrul de caractere scrise pn n acest moment este memorat la argumentul de tip int +. &u se face nici o con1ersie. :e scrie un caracter #. &u se face nici o con1ersie. :pecifica+ia complet este %%.

p n %

Caloare returnat Func+iile returnea3 numrul de caractere generate 9nu se include caracterul terminator null pentru sprintf<.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7B7

11.+. .ratarea erorilor


&ume perror 2 afi#ea3 un mesaj de eroare sistem
$eclara+ie -oid perror(const char +s); #include <errno.h> const char +s9sUerrlist)*; int s9sUnerr; $escriere Rutina perror afi#ea3 un mesaj la ie#irea standard de eroare* care descrie ultima eroare ntlnit la ultimul apel sistem sau func+ie de bibliotec. %ai nti se afi#ea3 argumentul s* apoi 1irgula #i blanc* #i n final mesajul de eroare #i ne'2line. :e recomand 9mai ales pentru depanare< ca argumentul s s includ numele func+iei n care a aprut eroarea. Codul erorii se ia din 1ariabila e-tern errno. Lista global de erori s9sUerrlist)* inde-at cu errno poate fi folosit pentru a ob+ine mesajul de eroare fr ne'2line. ,ltimul indice de mesaj din list este s9sUnerr6'. :e recomand o aten+ie deosebit n ca3ul accesului direct la list deoarece unele coduri noi de eroare pot lipsi din s9sUerrlist)*. $ac un apel sistem e#uea3 1ariabila errno indic codul erorii. 6ceste 1alori pot fi gsite n <errno.h>. Func+ia perror ser1e#te la afi#area acestui cod de eroare ntr2o form li3ibil. $ac un apel terminat cu eroare nu este imediat urmat de un apel perror* 1aloarea 1ariabilei errno se poate pierde dac nu e sal1at.

&ume clearerr* feof* ferror 2 1erific #i resetea3 starea flu-ului


$eclara+ie -oid clearerr(=J>@ +flu8);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7B8

int feof(=J>@ +flu8); int ferror(=J>@ +flu8); int fileno( =J>@ +flu8); $escriere Func+ia clearerr #terge indicatorii de sfr#it de fi#ier #i eroare ai flu-ului. Func+ia feof testea3 indicatorul de sfr#it de fi#ier al flu-ului* #i returnea3 non23ero dac este setat. 6cesta este setat dac o opera+ie de citire a detectat sfr#itul de fi#ier. Func+ia ferror testea3 indicatorul de eroare al flu-ului* #i returnea3 non23ero dac este setat. 6cesta este setat dac o opera+ie de citire sau scriere a detectat o eroare 9datorat de e-emplu "ard'are2ului<. Func+iile de citire 9cu sau fr format< nu fac distinc+ie ntre sfr#it de fi#ier #i eroare* astfel c trebuie apelate func+iile feof #i ferror pentru a determina cau3a. Func+ia fileno e-aminea3 argumentul flu8 #i returnea3 descriptorul asociat de sistemul de operare acestui flu-. :tenie@ Kste foarte frec1ent folosirea incorect a func+iei feof pentru a testa dac s2a ajuns la sfr#itul fi#ierului. &u se recomand n nici un ca3 acest stil de programare4 #define >MJV 50 char lin)>MJV*; =J>@ +fi,+fo; fi"fopen(nume-fiier-intrare,"rt"); fo"fopen(nume-fiier-ieire,"wt"); while (&feof(fi)) { =W gre#itR W= f7ets(lin,>MJV,fi); fputs(lin,fo); fclose(fi); fclose(fo); @n aceast sec1en+* dac #i ultima linie a fi#ierului te-t de intrare este terminat cu ne'2line* aceasta 1a fi scris de dou ori n fi#ierul de ie#ire. $e ceX $up ce se cite#te ultima linie nc nu este
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7B?

po3i+ionat indicatorul de sfr#it de fi#ier* deci func+ia f7ets returnea3 succes. La reluarea ciclului se ncearc un nou f7ets #i abia acum se depistea3 sfr#itul de fi#ier* fapt marcat n 3ona re3er1at flu-ului fi. 6stfel con+inutul tabloului lin rmne nemodificat #i este scris a doua oar n fi#ierul de ie#ire. 6bia la o nou reluare a ciclului func+ia feof ne spune c s2a depistat sfr#itul de fi#ier. @n acest manual snt pre3entate mai multe programe care efectuea3 diferite prelucrri asupra unor fi#iere te-t. 0entru simplitate toate programele presupun c nu apar erori la citire sau la scriere.

11.4. *peraii cu directoare


Func+iile de parcurgere a cataloagelor de fi#iere descrise n aceast sec+iune 9opendir* readdir* closedir< snt definite de mai multe medii de programare C 9Borland* atcom* Cisual C* L&, Linu-<* precum #i de standardul 0D:;O. 6ceste func+ii snt descrise n <dirent.h>. Func+iile de redenumire #i #tergere a unor fi#iere snt descrise n <stdio.h>.

&ume opendir 2 desc"ide un director


$eclara+ie EJV +opendir(const char +nume); $escriere Func+ia opendir desc"ide un flu- pentru directorul cu numele nume* #i returnea3 un pointer la flu-ul desc"is. Flu-ul este po3i+ionat pe prima intrare din director. Caloare returnat Func+ia returnea3 un pointer la flu- n ca3 de succes* sau A?>> n ca3 de eroare #i 1ariabila global errno indic codul erorii.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7BA

Cte1a erori posibile @<DD@M 6cces inter3is @ASREJV nume nu este un director

&ume readdir 2 cite#te un director


$eclara+ie struct dirent +readdir(EJV +dir); $escriere Func+ia readdir returnea3 un pointer la o structur de tip dirent care repre3int urmtoarea intrare din directorul indicat de flu-ul dir. Returnea3 A?>> dac s2a depistat sfr#itul de director sau dac a aprut o eroare. :tructura de tip dirent con+ine un cmp char dUname)*. ,tili3area altor cmpuri din structur reduce portabilitatea programelor. Caloare returnat Func+ia returnea3 un pointer la o structur de tip dirent* sau A?>> dac s2a depistat sfr#itul de director sau dac a aprut o eroare.

&ume closedir 2 nc"ide un director


$eclara+ie int closedir(EJV +dir); $escriere Func+ia closedir nc"ide flu-ul dir. Caloare returnat Func+ia returnea3 0 n ca3 de succes sau @S= n ca3 de eroare.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7BB

&ume rename 2 redenume#te un fi#ier remove 2 #terge un fi#ier


$eclara+ie int rename(const char +old, const char +new); int remo-e(const char +name); $escriere Func+ia rename sc"imb numele unui fi#ier din old n new. $ac a fost preci3at un periferic n new* acesta trebuie s coincid cu cel din old. $irectoarele din old #i new pot s fie diferite* astfel c rename poate fi folosit pentru a muta un fi#ier dintr2un director n altul. &u se permit specificatori generici 9'ildcards<. Func+ia remo-e #terge fi#ierul specificat prin name. Caloare returnat @n ca3 de succes se returnea3 0. @n ca3 de eroare se returnea3 @S= #i 1ariabila global errno indic codul erorii.

11.5. Programe demonstrati$e


0rimele trei programe primesc ca parametri n linia de comand numele fi#ierelor pe care le 1or prelucra. ,ltimul program prime#te ca parametru n linia de comand numele directorului al crui con+inut 1a fi afi#at. 7< $eterminarea mrimii unui fi#ier #include <stdio.h> =J>@ +f; int main(int ac, char ++a-) { if (ac&".) { fputs("?n ar7ument&\n",stderr); return ';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7BE

f " fopen(a-)'*,"r("); if (&f) { perror("@roare la deschidere"); return '; fsee,(f,0,M@@NU@AE); fprintf(stderr,"=ile #s, si:e #ld\n", ftell(f)); fclose(f); return 0; 8< Copierea unui fi#ier Func+iile f7ets #i fputs se folosesc pentru flu-uri desc"ise n mod te-t. Cum se utili3ea3 pentru copierea unui fi#ier te-tX #include <stdio.h> #define >MJV 50 char lin)>MJV*; =J>@ +fi, +fo; int main(int ac, char ++a-) { if (ac&"0) { fputs("Eoua ar7umente&\n",stderr); fi"fopen(a-)'*,"rt"); fo"fopen(a-).*,"wt"); if (&fi HH &fo) { perror("@roare la deschidere"); return '; while (f7ets(lin,>MJV,fi)) fputs(lin,fo); fclose(fi); fclose(fo); return 0; Func+iile fread #i fwrite se folosesc pentru flu-uri desc"ise n mod binar. Cum se utili3ea3 pentru copierea unui fi#ier binarX
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7B7

#include <stdio.h> #define >TSA 50 char :on)>TSA*; =J>@ +fi, +fo; int ,; int main(int ac, char ++a-) { if (ac&"0) { fputs("Eoua ar7umente&\n",stderr); return '; fi"fopen(a-)'*,"r("); fo"fopen(a-).*,"w("); if (&fi HH &fo) { perror("@roare la deschidere"); return '; while (,"fread(:on,',>TSA,fi)) fwrite(:on,',,,fo); fclose(fi); fclose(fo); return 0; ?< 0relucrarea unui fi#ier te-t 0rogramul pre3entat n continuare cite#te un fi#ier te-t care con+ine pe fiecare linie un #ir de caractere 9fr spa+ii< #i trei 1alori ntregi* #i afi#ea3 pe terminal numele pe 78 po3i+ii aliniat la stnga #i media aritmetic a celor trei 1alori ntregi. #include <stdio.h> =J>@ +fi; char num)'0*; int a,(,c; dou(le m; int main(int ac, char ++a-) { if (ac&".) { fputs("?n ar7ument&\n",stderr);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7BG

return '; fi"fopen(a-)'*,"rt"); if (&fi) { perror("@roare la deschidere"); return '; while (fscanf(fi,"#s #d #d #d", num,$a,$(,$c)&"@S=) { m"(a%(%c)F0.0; printf("#6'.s#2..lf\n",num,m); fclose(fi); return 0; A< 6fi#area con+inutului unui director #include <dirent.h> #include <stdio.h> EJV +dir; struct dirent +ent; int main(int ac, char ++a-) { if (ac&".) { printf("?n parametru\n"); return '; dir " opendir(a-)'*); if (&dir) { perror("@roare open dir"); return '; while (ent"readdir(dir)) printf("#s\n",ent6>dUname); return 0;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7BH

12. :lte rutine din biblioteca standard


@n acest capitol snt descrise func+ii care re3ol1 probleme legate de alocarea dinamic a memoriei* sortare #i cutare* clasificare* opera+ii cu blocuri de memorie #i #iruri de caractere* func+ii matematice.

12.1. :locarea dinamic a memoriei


&ume calloc* malloc* realloc 2 aloc memoria n mod dinamic free 2 eliberea3 memoria alocat n mod dinamic
$eclara+ie #include <stdli(.h> -oid +calloc(unsi7ned nel, unsi7ned si:e); -oid +malloc(unsi7ned si:e); -oid +realloc(-oid +ptr, unsi7ned si:e); -oid free(-oid +ptr); $escriere Func+ia calloc aloc memorie pentru un tablou de nel elemente* fiecare de mrime si:e octe+i #i returnea3 un pointer la memoria alocat. Con+inutul memoriei este pus la 3ero. Func+ia malloc aloc si3e octe+i #i returnea3 un pointer la memoria alocat. Con+inutul memoriei nu este #ters. Func+ia free eliberea3 spa+iul de memorie indicat de ptr* care trebuie s fi fost returnat de un apel anterior malloc* calloc sau realloc. @n ca3 contrar* sau dac a e-istat deja un apel anterior free(ptr)* comportamentul programului este impre1i3ibil. Func+ia realloc sc"imb mrimea blocului de memorie indicat de ptr la si:e octe+i. Con+inutul rmne nesc"imbat la mrimea minim dintre mrimea 1ec"e #i cea nou; noul spa+iu de memorie
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E0

care este e1entual alocat este neini+iali3at. $ac ptr este A?>> apelul este ec"i1alent cu malloc(si:e); dac si:e este egal cu 3ero apelul este ec"i1alent cu free(ptr). Cu e-cep+ia ca3ului cnd ptr este A?>>* acesta trebuie s fi fost returnat de un apel precedent malloc* calloc sau realloc. Calori returnate 0entru calloc #i malloc 1aloarea returnat este un pointer la memoria alocat* care este aliniat n mod corespun3tor pentru orice tip de 1ariabile* sau A?>> dac nu e-ist suficient memorie continu. Func+ia free nu returnea3 nimic. Func+ia realloc returnea3 un pointer la noua 3on de memorie alocat* care este aliniat n mod corespun3tor pentru orice tip de 1ariabile* #i poate fi diferit de ptr* sau poate fi A?>> dac nu e-ist suficient memorie continu sau dac 1aloarea si:e este egal cu 0. $ac realloc e#uea3* blocul original rmne neatins 2 nu este nici eliberat nici mutat.

12.2. ,ortare i cutare


&ume *sort 2 sortea3 un tablou bsearch 2 cutare binar ntr2un tablou sortat
$eclara+ie #include <stdli(.h> -oid Isort(-oid +(ase, unsi7ned nel, unsi7ned si:e, int (+comp) (const -oid +, const -oid +)); -oid +(search(const -oid +,e9, const -oid +(ase, unsi7ned nel, unsi7ned si:e, int (+comp)(const -oid +, const -oid +)); $escriere
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E7

Func+ia Isort sortea3 un tablou de nel elemente* fiecare de mrime si:e. 6rgumentul (ase indic spre nceputul tabloului. Klementele tabloului snt sortate n ordine cresctoare n concordan+ cu func+ia de comparare referit de comp* apelat cu dou argumente care indic spre obiectele ce se compar. Func+ia de comparare trebuie s returne3e un ntreg mai mic dect* egal cu* sau mai mare dect 3ero dac primul argument este considerat a fi mai mic dect* egal cu* respecti1 mai mare dect al doilea. $ac cele dou elemente comparate snt egale* ordinea n tabloul sortat este nedefinit. Func+ia (search caut ntr2un tablou de nel elemente* fiecare de mrime si:e* un membru care coincide cu obiectul indicat de ,e9. 6rgumentul (ase indic spre nceputul tabloului. Con+inutul tabloului trebuie s fie sortat cresctor n concordan+ cu func+ia de comparare referit de comp* apelat cu dou argumente care indic spre obiectele ce se compar. Func+ia de comparare trebuie s returne3e un ntreg mai mic dect* egal cu* sau mai mare dect 3ero dac primul argument este considerat a fi mai mic dect* egal cu* respecti1 mai mare dect al doilea. Caloare returnat Func+ia (search returnea3 un pointer la un membru al tabloului care coincide cu obiectul indicat de ,e9* sau A?>> dac nu se gse#te nici un membru. $ac e-ist mai multe elemente care coincid cu ,e9* poate fi returnat oricare element cu aceast proprietate.

12.3. ;utine de clasi#icare


&ume isalnum* isalpha* isascii* iscntrl* isdigit* isgraph* islower* isprint* ispunct* isspace* isupper* isxdigit 2 rutine de clasificare tolower 2 con1ersie n liter mic toupper 2 con1ersie n liter mare
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E8

$eclara+ie #include <ct9pe.h> int isalnum(int c); int isalpha(int c); int isascii(int c); int iscntrl(int c); int isdi7it(int c); int is7raph(int c); int tolower(int c);

int int int int int int

islower(int c); isprint(int c); ispunct(int c); isspace(int c); isupper(int c); is8di7it(int c);

int toupper(int c);

$escriere 0rimele 78 func+ii 1erific dac c* care trebuie s fie o 1aloare de tip unsi7ned char sau @S=* se afl n una din clasele de caractere enumerate mai sus. isalnum Cerific dac c este alfanumeric; este (isalpha(c) HH isdi7it(c)). ec"i1alent cu

isalpha Cerific dac c este alfabetic; este ec"i1alent cu (isupper(c) HH islower(c)). isascii Cerific dac c este o 1aloare pe 7 bi+i din setul de caractere 6:C;;. iscntrl Cerific dac c este un caracter de control. isdi7it Cerific dac c este o cifr 9ntre 0 #i H<. is7raph Cerific dac c este un caracter afi#abil cu e-cep+ia spa+iului. islower Cerific dac c este o liter mic.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E?

isprint Cerific dac c este un caracter afi#abil inclusi1 spa+iu. ispunct Cerific dac c este un caracter diferit de spa+iu #i non2 alfanumeric. isspace Cerific dac c este un spa+iu alb. isupper Cerific dac c este o liter mare. is8di7it Cerific dac c este o cifr "e-a3ecimal din setul 0 7 8 ? A B E 7 G H a b c d e f 6 B C $ K F. tolower Con1erte#te caracterul c* dac este o liter* la litera mic corespun3toare. toupper Con1erte#te caracterul c* dac este o liter* la litera mare corespun3toare. Caloare returnat Caloarea returnat de func+iile is... este nenul dac caracterul c se afl n clasa testat* #i 3ero n ca3 contrar. Caloarea returnat de func+iile to... este litera con1ertit dac caracterul c este o liter* #i nedefinit n ca3 contrar.

12.'. *peraii cu blocuri de memorie


0entru majoritatea func+iilor din aceast categorie compilatorul e-pandea3 codul acestora folosind instruc+iuni pe #iruri de caractere. $eclara+iile acestor func+ii se ob+in cu #include <strin7.h>

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7EA

&ume memcpy 2 copia3 o 3on de memorie


$eclara+ie -oid +memcp9(-oid +dest, const -oid +src, unsi7ned n); -oid +memmo-e(-oid +dest, const -oid +src, unsi7ned n); $escriere Func+ia memcp9 copia3 n octe+i din 3ona de memorie src n 3ona de memorie dest. Qonele de memorie nu trebuie s se suprapun. $ac e-ist acest risc se utili3ea3 memmo-e. Caloare returnat Func+iile returnea3 un pointer la dest.

&ume memcmp 2 compar dou 3one de memorie


$eclara+ie int memcmp(const -oid +s', const -oid +s., unsi7ned n); $escriere Func+ia memcmp compar primii n octe+i ai 3onelor de memorie s' #i s.. Caloare returnat Returnea3 un ntreg mai mic dect* egal cu* sau mai mare dect 3ero dac s' este mai mic dect* coincide* respecti1 este mai mare dect s..

&ume memset 2 umple o 3on de memorie cu o constant pe un octet


$eclara+ie
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7EB

-oid +memset(-oid +s, int c, unsi7ned n); $escriere Func+ia memset umple primii n octe+i ai 3onei de memorie indicat de s cu constanta c pe un octet. Caloare returnat Func+ia returnea3 un pointer la 3ona de memorie s.

&ume memchr 2 caut n memorie un caracter


$eclara+ie -oid +memchr(const -oid +s, int c, unsi7ned n); $escriere Func+ia memchr caut caracterul c n primii n octe+i de memorie indica+i de s. Cutarea se opre#te la primul octet care are 1aloarea c 9interpretat ca unsi7ned char<. Caloare returnat Func+ia returnea3 un pointer la octetul gsit sau A?>> dac 1aloarea nu e-ist n 3ona de memorie.

12.). *peraii cu iruri de caractere


0entru majoritatea func+iilor din aceast categorie compilatorul e-pandea3 codul acestora folosind instruc+iuni pe #iruri de caractere. $eclara+iile acestor func+ii se ob+in cu #include <strin7.h>

&ume strlen 2 calculea3 lungimea unui #ir


$eclara+ie unsi7ned strlen(const char +s); $escriere
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7EE

Func+ia strlen calculea3 lungimea #irului s* fr a include caracterul terminator null. Caloare returnat Func+ia returnea3 numrul de caractere din s.

&ume strcpy* strncpy 2 copia3 un #ir de caractere


$eclara+ie char +strcp9(char +dest, const char +src); char +strncp9(char +dest, const char +src, unsi7ned n); $escriere Func+ia strcp9 copia3 #irul indicat de src 9inclusi1 caracterul terminator null< n 3ona indicat de dest. birurile nu trebuie s se suprapun* #i n plus 3ona dest trebuie s fie suficient de mare pentru a primi copia. Func+ia strncp9 este similar* cu e-cep+ia faptului c nu se copia3 mai mult de n octe+i din src. 6stfel* dac caracterul terminator null nu se afl n primii n octe+i din src* re3ultatul nu 1a fi terminat cu null. @n ca3ul n care lungimea lui src este mai mic dect n* restul octe+ilor din dest primesc 1aloarea null. Caloare returnat Func+iile returnea3 un pointer la #irul dest.

&ume strdup 2 duplic un #ir


$eclara+ie char +strdup(const char +s); $escriere Func+ia strdup returnea3 un pointer la un nou #ir care este un duplicat al #irului s. %emoria pentru noul #ir se ob+ine cu malloc* #i poate fi eliberat cu free.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7E7

Caloare returnat Func+ia returnea3 un pointer la #irul duplicat* sau A?>> dac nu e-ist memorie suficient disponibil.

&ume strcat* strncat 2 concatenea3 dou #iruri


$eclara+ie char +strcat(char +dest, const char +src); char +strncat(char +dest, const char +src, unsi7ned n); $escriere Func+ia strcat adaug #irul src la #irul dest suprascriind caracterul null de la sfr#itul lui dest* #i la sfr#it adaug un caracter terminator null. birurile nu trebuie s se suprapun* #i n plus #irul dest trebuie s aib suficient spa+iu pentru a pstra re3ultatul. Func+ia strncat este similar* cu e-cep+ia faptului c numai primele n caractere din src se adaug la dest. Caloare returnat Func+iile returnea3 un pointer la #irul re3ultat dest.

&ume strcmp 2 compar dou #iruri de caractere


$eclara+ie int strcmp(const char +s', const char +s.); $escriere Func+ia strcmp compar cele dou #iruri s' #i s.. Caloare returnat Func+ia returnea3 un ntreg mai mic dect* egal cu* sau mai mare dect 3ero dac s' este mai mic dect* coincide* respecti1 este mai mare dect s..
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7EG

&ume strchr* strrchr 2 locali3ea3 un caracter


$eclara+ie char +strchr(const char +s, int c); char +strrchr(const char +s, int c); $escriere Func+ia strchr returnea3 un pointer la prima apari+ie a caracterului c n #irul s. Func+ia strrchr returnea3 un pointer la ultima apari+ie a caracterului c n #irul s. Caloare returnat Func+iile returnea3 un pointer la caracterul gsit sau A?>> dac 1aloarea nu a fost gsit.

&ume strstr 2 locali3ea3 un sub#ir


$eclara+ie char +strstr(const char +sir, const char +su(s); $escriere Func+ia strstr gse#te prima apari+ie a sub#irului su(s n #irul sir. Caracterul terminator null nu este luat n considerare. Caloare returnat Func+ia returnea3 un pointer la nceputul sub#irului* sau A?>> dac sub#irul nu este gsit.

&ume strspn* strcspn 2 caut un set de caractere ntr2un #ir


$eclara+ie unsi7ned strspn(const char +s, const char
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7EH

+acc); unsi7ned strcspn(const char +s, const char +reG); $escriere Func+ia strspn calculea3 lungimea segmentului ini+ial din s format n ntregime numai cu caractere din acc. Func+ia strcspn calculea3 lungimea segmentului ini+ial din s format n ntregime numai cu caractere care nu se gsesc n reG. Calori returnate Func+ia strspn returnea3 po3i+ia primului caracter din s care nu se afl n acc. Func+ia strcspn returnea3 po3i+ia primului caracter din s care se afl n reG.

12.+. Aiblioteca matematic


7< Func+iile din prima categorie snt descrise n <stdli(.h>.

&ume rand* srand 2 generarea numerelor pseudo2aleatoare


$eclara+ie int rand(-oid); -oid srand(unsi7ned int seed); $escriere Func+ia rand returnea3 un ntreg pseudo2aleator ntre 0 #i V<AEUB<; 9pentru majoritatea mediilor de programare C aceast constant este egal cu 1aloarea ma-im cu semn repre3entabil pe un cu1nt al sistemului de calcul<. Func+ia srand ini+iali3ea3 generatorul cu 1aloarea seed pentru o nou sec1en+ de 1alori ntregi pseudo2aleatoare care 1or fi returnate de rand. 6ceste sec1en+e se repet dac srand se apelea3 cu aceea#i 1aloare seed. :e obi#nuie#te ca generatorul s fie ini+iali3at cu o 1aloare dat de ceasul sistemului de calcul* ca n e-emplul de mai jos4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

770

#include <time.h> srand(time(A?>>)); Caloare returnat Func+ia rand returnea3 o 1aloare ntre 0 #i V<AEUB<;. Dbser1a+ie @n lucrarea )umerical .ecipes in */ The Art of &cientific *omputin 2 illiam M 0ress* Brian 0 Flanner)* :aul 6 /euIolsI)* illiam / Cetterling = &e' PorI4 Cambridge ,ni1ersit) 0ress* 7HH0 97st ed* p 807<* se face urmtorul comentariu4 S$ac dori+i s genera+i o 1aloare aleatoare ntreag ntre 7 #i 70* se recomand s folosi+i sec1en+a G"'%(int)('0.0+rand()F(V<AEUB<;%'.0)); #i nu o sec1en+ de tipul G"'%(int)('000000.0+rand())#'0; care folose#te bi+ii de rang inferior.S /ot n fi#ierul <stdli(.h> snt descrise #i urmtoarele func+ii4 int a(s(int i); 1aloare absolut lon7 la(s(lon7 i); 1aloare absolut int atoi(char +s); con1ersie din 6:C;; n ntreg lon7 atol(char +s); con1ersie din 6:C;; n ntreg lung dou(le atof(char +s); con1ersie din 6:C;; n dubl preci3ie 8< Func+iile din a doua categorie snt descrise n fi#ierul <math.h>. dou(le dou(le dou(le dou(le dou(le dou(le dou(le dou(le fa(s(dou(le 8); 1aloare absolut floor(dou(le 8); parte ntreag inferioar ceil(dou(le 8); parte ntreag superioar sIrt(dou(le 8); x sin(dou(le 8); sin9x< cos(dou(le 8); cos9x< tan(dou(le 8); tg9x< asin(dou(le 8); arcsin9x<
777

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

dou(le acos(dou(le 8); arccos9x< dou(le atan(dou(le 8); arctg9x< n Y2F8*F8[ dou(le atan.(dou(le 9, dou(le 8); arctg9y/x< n Y5*[ dou(le e8p(dou(le 8); ex dou(le lo7(dou(le 8); ln9x< dou(le pow(dou(le 8, dou(le 9); xy dou(le sinh(dou(le 8); sin"9x< dou(le cosh(dou(le 8); cos"9x< dou(le tanh(dou(le 8); tg"9x< dou(le lde8p(dou(le 8, int e); x 8e dou(le fmod(dou(le 8, dou(le 9); x modulo y Func+ia fmod returnea3 o 1aloare f definit astfel4 x = a y + f a este o 1aloare ntreag 9dat de xFy< #i 0 _f _ g y; f are semnul lui x. ,rmtoarele dou func+ii returnea3 dou 1alori4 una este 1aloarea returnat de func+ie 9de tip dou(le<* #i cealalt returnat prin intermediul unui argument de tip pointer la int respecti1 dou(le. dou(le fre8p(dou(le 8, int +e); Func+ia fre8p desparte 1aloarea x n dou pr+i4 o parte frac+ionar normali3at 9f Y0.B*7<< #i un e-ponent e. $ac x este 0 atunci f=0 #i e=0. Caloarea returnat este f. dou(le modf(dou(le 8, dou(le +n); Func+ia modf desparte 1aloarea x n dou pr+i4 o parte frac+ionar subunitar f #i o parte ntreag n. Calorile f #i n au acela#i semn ca #i x. Caloarea returnat este f.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

778

12.4. Programe demonstrati$e


7< 0rogramul pre3entat n continuare generea3 un #ir de n 1alori ntregi aleatoare n inter1alul Y0* B7[ pe care le depune n tabloul ; 9alocat dinamic<* #i apoi le sortea3 cresctor. @n continuare se generea3 , 1alori ntregi aleatoare pe care le caut n tabloul ;. 0entru fiecare cutare cu succes se afi#ea3 pe terminal 1aloarea cutat #i po3i+ia n tablou. Calorile n* , #i B se iau n aceast ordine din linia de comand. #include <stdli(.h> #include <stdio.h> #include <time.h> int cmp(const -oid +<, const -oid +C) { return +(int +)<6+(int +)C; int main(int ac, int ++a-) { int +;,+p,B,n,,,i,-; if (ac&"/) { fputs("Rrei ar7umente&\n",stderr); return '; n"atoi(a-)'*); ,"atoi(a-).*); B"atoi(a-)0*); ;"(int +)malloc(n+si:eof(int)); if (&;) return '; srand(time(A?>>)); for (i"0; i<n; i%%) ;)i*"rand()#B; Isort(;,n,si:eof(int),cmp); for (i"0; i<,; i%%) { -"rand()#B; p"(int +)(search($-,;,n,si:eof(int), cmp); if (p) printf("QalP #d ZosP #d\n",-,p6;);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77?

free(;); return 0; 8< : relum al treilea e-emplu din capitolul precedent. :e cite#te un fi#ier te-t care con+ine pe fiecare linie un nume 9#ir de caractere fr spa+iu< #i trei 1alori reale 9note<. 0entru fiecare linie se calculea3 media aritmetic a celor trei 1alori #i se determin dac elementul este admis 9fiecare not este minimum B< sau respins 9cel pu+in o not este sub B<. @n final se afi#ea3 liniile n ordinea urmtoare4 mai nti elementele admise n ordinea descresctoare a mediei* #i apoi elementele respinse n ordine alfabetic dup nume. :e afi#ea3 doar numele* situa+ia 9<FV< #i media. @n acest e-emplu punem n e1iden+ o modalitate comod de selectare a membrilor unei structuri cu ajutorul macrourilor. %acroul =ld selectea3 din 3ona referit de pointerul Z membrul f. $eoarece pointerul Z 9care poate fi argumentul < sau C al func+iei comp< refer o 3on de tip -oid* este necesar mai nti un cast pentru a preci3a tipul concret al acesteia. %embrul f poate fi4 nm* ar* md* defini+i n cadrul structurii de tip Mt@l. $eoarece nu #tim de la nceput cte linii are fi#ierul de intrare* sntem ne1oi+i s folosim urmtoarea strategie. La nceput alocm pentru tabloul @l o 3on care s memore3e A< elemente. 0e msur ce aceast 3on se completea3* la un moment dat numrul de linii citite coincide cu A<. @n acest moment se aloc o 3on nou care s poat memora un numr mai mare de elemente. $esigur* de fiecare dat se 1a actuali3a mrimea spa+iului alocat. #include <stdli(.h> #include <strin7.h> #include <stdio.h> #define A< 0. t9pedef struct { char nm)'0*, ar; float na, n(, nc, md; Mt@l;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77A

#define =ld(Z,f) ((Mt@l +)Z)6>f int comp(const -oid +<, const -oid +C) { float w; int d; if (d"=ld(<,ar)6=ld(C,ar)) return d; if (=ld(<,ar)""!<!) { w"=ld(C,md)6=ld(<,md); if (w>0) return '; if (w<0) return 6'; return strcmp(=ld(<,nm),=ld(C,nm)); int main(int ac, char ++a-) { int na,ne,i; Mt@l +@l; =J>@ +fi; if (ac&".) { fputs("?n ar7ument&\n",stderr); return '; fi"fopen(a-)'*,"rt"); if (&fi) { perror("@roare la deschidere"); return '; na"A<; ne"0; @l"(Mt@l +)malloc(na+si:eof(Mt@l)); while (fscanf(fi,"#s #d #d #d", @l)ne*.nm,$@l)ne*.na,$@l)ne*.n(, $@l)ne*.nc)&"@S=) { if ((@l)ne*.na>"1) $$ (@l)ne*.n(>"1) $$ (@l)ne*.nc>"1)) @l)ne*.ar"!<!; else @l)ne*.ar"!V!; @l)ne*.md"(@l)ne*.na%@l)ne*.n(% @l)ne*.nc)F0.0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77B

ne%%; if (ne""na) { na%"A<; @l"(Mt@l +)realloc(@l,na+ si:eof(Mt@l)); fclose(fi); Isort(@l,ne,si:eof(Mt@l),comp); for (i"0; i<ne; i%%) printf("#6'.s #c#2..lf\n", @l)i*.nm,@l)i*.ar,@l)i*.md); free(@l); return 0; ?< :e cite#te dintr2un fi#ier te-t o 1aloare natural n. ,rmtoarele linii con+in n cu1inte* fiecare cu1nt a1nd acela#i numr de litere 9cel mult 70<. : se afi#e3e cu1intele din fi#ier ordonate alfabetic. 0entru a memora lista de cu1inte folosim urmtoarea strategie. @n loc s alocm pentru fiecare cu1nt 9#ir de caractere< citit o 3on nou de memorie* alocm de la nceput o 3on n care s putem memora toate cu1intele din list. 6ceast 3on 1a a1ea mrimea de (l%')+n octe+i* unde l este lungimea fiecrui cu1nt 9numrul de litere<. $e ce (l%')X pentru c trebuie s memorm #i caracterul terminator null. 61antaje4 memoria este utili3at mai eficient dac se aloc de la nceput o 3on contigu de dimensiune mai mare* #i se reduce foarte mult fragmentarea memoriei. #include <stdli(.h> #include <strin7.h> #include <stdio.h> int comp(const -oid +<, const -oid +C) { return strcmp((char +)<,(char +)C); int main(int ac, char ++a-) { char +D,s)''*;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77E

int n,l,i; =J>@ +fi; if (ac&".) { fputs("?n ar7ument&\n",stderr); return '; fi"fopen(a-)'*,"rt"); if (&fi) { perror("@roare la deschidere"); return '; fscanf(fi,"#d #s",n,s); l"strlen(s); D"(char +)malloc((l%')+n); Mtrcp9(D,s); for (i"'; i<n; i%%) fscanf(fi,"#s",D%(l%')+i); fclose(fi); Isort(D,n,l%',comp); for (i"0; i<n; i%%) printf("#s\n",D%(l%')+i); free(D); return 0;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

777

Aibliogra#ie
Brian !ernig"am* $ennis % Ritc"ie 2 The * 0ro rammin !an ua e 0rentice2Mall :oft'are :eries* 7H7G 2 !imba,ul *; manual de pro ramare ;nstitutul de te"nic de calcul* Cluj2&apoca 7HGA Merbert :c"ildt 2 1anual * complet Kditura /eora* 7HHG

%anuale electronice
"ttp4=='''.programmingtutorials.com=c."tml %ars"all Brain 2 %ntroduction to * 0ro rammin "ttp4==de1central.iftec".com=learning=tutorials=c2cpp=c= :te1e :ummit 2 %ntroductory * 0ro rammin *lass )otes "ttp4=='''.esIimo.com=]scs=cclass=cclass."tml :te1e :ummit 2 %ntermediate * 0ro rammin *lass )otes "ttp4=='''.esIimo.com=]scs=cclass=cclass."tml Brian Bro'n 2 * 0ro rammin "ttp4=='''.cit.ac.n3=smac=cprogram=onlinet."tm Brian Bro'n 2 An %ntroduction to * 0ro rammin "ttp4=='''.cit.ac.n3=smac=cprogram=default."tm

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77G

Cuprins
7. Leneralit+i asupra limbajului C . . . . . . . . . . . . . . . . . . . A
7.7. ;ntroducere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A 7.8. 0rimele programe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B 7.?. %eta2limbajul #i setul de caractere . . . . . . . . . . . . . . . . . . . . H

8. ,nit+ile le-icale ale limbajului C . . . . . . . . . . . . . . . . 70


8.7. ;dentificatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 8.8. Cu1inte c"eie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 8.?. Constante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 8.A. biruri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7A 8.B. Dperatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7B 8.E. :eparatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7B

?. Cariabile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
?.7. Clase de memorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 ?.8. /ipuri de 1ariabile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 ?.?. Dbiecte #i 1alori2stnga . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8? ?.A. Con1ersii de tip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8?

A. Dperatori #i e-presii . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
A.7. K-presii primare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 A.8. Dperatori unari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8H A.?. Dperatori multiplicati1i . . . . . . . . . . . . . . . . . . . . . . . . . . . ?8 A.A. Dperatori aditi1i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?? A.B. Dperatori de deplasare . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?? A.E. Dperatori rela+ionali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?A A.7. Dperatori de egalitate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?B A.G. Dperatorul b; pe bi+i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?B A.H. Dperatorul :6,2e-clusi1 pe bi+i . . . . . . . . . . . . . . . . . . . . ?B A.70. Dperatorul :6,2inclusi1 pe bi+i . . . . . . . . . . . . . . . . . . . . ?E A.77. Dperatorul b;2logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?E A.78. Dperatorul :6,2logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?7 A.7?. Dperatorul condi+ional . . . . . . . . . . . . . . . . . . . . . . . . . . . ?7 A.7A. Dperatori de atribuire . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?G
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

77H

A.7B. Dperatorul 1irgul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?H A.7E. 0receden+a #i ordinea de e1aluare . . . . . . . . . . . . . . . . . . . A0

B. $eclara+ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A8
B.7. :pecificatori de clas de memorie . . . . . . . . . . . . . . . . . . . A? B.8. :pecificatori de tip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AA B.?. $eclaratori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AB B.A. %odificatorul const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A7 B.B. ;ni+iali3are . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AG B.E. )ume-tip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AH

E. ;nstruc+iuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B7
E.7. ;nstruc+iunea expresie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B7 E.8. ;nstruc+iunea compus sau blocul . . . . . . . . . . . . . . . . . . . . B7 E.?. ;nstruc+iunea condi+ional . . . . . . . . . . . . . . . . . . . . . . . . . . B8 E.A. ;nstruc+iunea while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BA E.B. ;nstruc+iunea do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BA E.E. ;nstruc+iunea for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BB E.7. ;nstruc+iunea switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . BE E.G. ;nstruc+iunea (rea, . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BG E.H. ;nstruc+iunea continue . . . . . . . . . . . . . . . . . . . . . . . . . . BG E.70. ;nstruc+iunea return . . . . . . . . . . . . . . . . . . . . . . . . . . . BH E.77. ;nstruc+iunea 1id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BH

7. Func+iile #i structura unui program . . . . . . . . . . . . . . . . E0


7.7. $efini+ia func+iilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E0 7.8. 6pelul func+iilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E? 7.?. Re1enirea din func+ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .E? 7.A. 6rgumentele func+iei #i transmiterea parametrilor . . . . . . . EA 7.B. Func+ii cu numr 1ariabil de parametri . . . . . . . . . . . . . . . . EB 7.E. K-emple de func+ii #i programe . . . . . . . . . . . . . . . . . . . . . EE

G. Liniile de control ale compilatorului . . . . . . . . . . . . . . . 70


G.l. @nlocuirea simbolurilor* substitu+ii macro . . . . . . . . . . . . . . 70 G.8. ;ncluderea fi#ierelor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 G.?. Compilarea condi+ionat . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 G.A. ,tili3area directi1elor de compilare . . . . . . . . . . . . . . . . . . 7?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7G0

H. 0ointeri #i masi1e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7E
H.7. 0ointeri #i adrese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7E H.8 0ointeri #i argumente de func+ii . . . . . . . . . . . . . . . . . . . . . . 77 H.?. 0ointeri #i masi1e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7G H.A. 6ritmetica de adrese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . G0 H.B. 0ointeri la caracter #i func+ii . . . . . . . . . . . . . . . . . . . . . . . . G? H.E. %asi1e multidimensionale . . . . . . . . . . . . . . . . . . . . . . . . . GE H.7. %asi1e de pointeri #i pointeri la pointeri . . . . . . . . . . . . . . GG H.G. ;ni+iali3area masi1elor #i masi1elor de pointeri . . . . . . . . . H? H.H. %asi1e de pointeri #i masi1e multidimensionale . . . . . . . . HE H.70. 6rgumentele unei linii de comand . . . . . . . . . . . . . . . . . H7 H.77. 0ointeri la func+ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708

70. :tructuri #i reuniuni . . . . . . . . . . . . . . . . . . . . . . . . . 70E


70.7. Klemente de ba3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70E 70.8. :tructuri #i func+ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70G 70.?. %asi1e de structuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 770 70.A. 0ointeri la structuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77B 70.B. :tructuri auto2referite . . . . . . . . . . . . . . . . . . . . . . . . . . . 777 70.E. Cutare n tabele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78? 70.7. Cmpuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787 70.G. Reuniuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78H 70.H. $eclara+ii de structuri* reuniuni #i cmpuri . . . . . . . . . . 7?7 70.70. R9pedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7??

77. ;ntrri = ie#iri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7?E


77.7. ;ntrri #i ie#iri standard; fi#iere . . . . . . . . . . . . . . . . . . . . 7?E 77.8. 6ccesul la fi#iere; desc"idere #i nc"idere . . . . . . . . . . . 7?G 77.?. Citire #i scriere fr format . . . . . . . . . . . . . . . . . . . . . . . 7A7 77.A. Citire cu format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7A? 77.B. :criere cu format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7A7 77.E. /ratarea erorilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7B8 77.7. Dpera+ii cu directoare . . . . . . . . . . . . . . . . . . . . . . . . . . . 7BA 77.G. 0rograme demonstrati1e . . . . . . . . . . . . . . . . . . . . . . . . 7BE

78. 6lte rutine din biblioteca standard . . . . . . . . . . . . . . 7E0


78.7. 6locarea dinamic a memoriei . . . . . . . . . . . . . . . . . . . . 7E0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7G7

78.8. :ortare #i cutare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7E7 78.?. Rutine de clasificare . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7E8 78.A. Dpera+ii cu blocuri de memorie . . . . . . . . . . . . . . . . . . . 7EA 78.B. Dpera+ii cu #iruri de caractere . . . . . . . . . . . . . . . . . . . . 7EE 78.E. Biblioteca matematic . . . . . . . . . . . . . . . . . . . . . . . . . . 770 78.7. 0rograme demonstrati1e . . . . . . . . . . . . . . . . . . . . . . . . . 77? Bibliografie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77G

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

7G8

You might also like