Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml


Manual de referinta C

c



+ Font mai mare | - Font mai mic



Manual de referinta C

1. Introducere

Acest manual descrie limbajul C implementat pe PDP-11,



Honeywele 6000, IBM System370 si Interdata 832. In

blocurile unde exista diferente (intre implemntari) el se

refera la PDP-11, dar se incearca punctarea detaliilor

dependente de implementare. Cu mici diferente, aceste

dependente sint legate direct de proprietatile hardware (ale

masinilor); diverselel compilatoare sint in general compatibile.

2. Conventii lexicale

Exista sase clase de simboluri: identificatori, cuvinte-cheie,

constante, (in mod colectiv numite 'spatii albe')asa cum vor fi

descrise in continuare. sint ignorate cu exceptia cazurilor cind

servesc la repararea simbolurilor. Unele spatii albe sint necesare

pentru a separa identificatori adiacenti, cuvint-cheie si

constante.

Daca sirul de intrare (pentru compilator) a fost analizat (si

transformat) in simboluri pina la un caracter dat, urmatorul

simbol va include cel mai lung sir de caractere care poate

constitui un simbol.

2. 1. Comentarii

Caracterele /* incep un comentariu, care se termina cu

caracterele*/. Comentariile nu pot fi imbricate.

2. 2 Identificatori (nume)

Un identificator este o secventa de litere si cifre;primul

caracter trebuie sa fie litera. Sublinierea (underscor) este

considerata litera literele mari si mici sint diferite. dDoar

primele 8 caractere sint semnificative, desi pot fi folosite mai

multe. Identificatorii externi care sint utilizati de o serie de

asamblare sau incarcatoare, sint mai restrictivi:

PDP-II 7 caractere, 2cazuri, casete (cases)

Homywele 6000 6caractere, 1caset.

IBM 360/370 7caractere, 1case

Interdata 8/32 8caractere, 2 cases

2. 3. Cuvinte cheie

Urmatorii idenntificatori sint rezervati pentru a fi folositi

ca si cuvinte cheie, si nu pot fi folositi altfel:

int extern else

char register for

float typedef do

double static while

struct goto switch

union return case

long sizeof default

short break entry

unsigned continue

auto if

Cuvintul cheie 'entry' nu este implementat de nici un

compilator, dar este rezervat pentru o utilizare ulterioara. Unele

implementari rezerva si cuvintele 'fortran' si 'asm'

2. 4. Constante

Exista o serie de contante decrise in continuare.

Caracteristicile hardware care afecteaza dimensiunile sint

rezumate in $2.

2. 4. 1. Constante intregi

O constanta intreaga constind dintr-o serie de cifre va fi

considerata in octal daca incepe cu 0 (cifra zero), astfel va fi

considerata in zecimal. O secvanta de cifre precedata de ox

sau OX (cifra zero) este considearata intreg hexazecimal.

Daca valoarea unei constante zecimale depaseste posibilitatile

hardware de inmagazinare a intregilor ea va fi considerata

de tip 'long'. Acelsi lucru se intimpla si pentru constantele

octale sau hexazecimale.

2. 4. 2. Constantelungi explicite

O constanta intreaga de tip octal, zecimal sau hexazecimal urmata

de caracterul 'l'sau'L' este considerata consatnta lunga. Dupa

cum va fi discutat la unele masini intregii si valorile 'long' pot

fi considerate identice.

2. 4. 3. Constante tip caracter

O constanta tip carcter este un caracter intre ghilimele simple

cum ar fi de exemplu '*'. Valoarea unei constante tip

caracter este valorea numerica a caracterului corepunzator

setului de caractere al masinii. Unele caractere negrafice,

cum sint ghilimeaua si backspace pot fi reprezentate dupa

cum urmeaza, conform unei tabele de secvente 'escape'.

newline NL(LP) n

horisontaltab HT t

backspace BS b

carriagereturn CR r

formfeed FF f

backslash

ghilimea ' '

modelbinar ddd ddd 'bit pattern'

Secventa ddd consta din caracterul backslash uramt de 1, 1 sau 3

cifre octale care vor specifica valorea unui caracter dorit. Un

caz special de constructie este 0 (neurmat de nici o cifra) care

indica un caracter NULL. Daca caracterul care urmeaza dupa nu

este de tipul specificat, se ignora .

2. 4. 4. Constante in virgula mobila

O constanta in virgula mobila consta dintr-o parte intreaga,

punct zecimal parte fractionara un 'e' sau 'E' si optional s un

intreg cu semn pe post de exponent.

Intregul si partea fractionara pot fi o secvente de cifre. Atit

intregul cit si partea fractionara (dar nu simultan ) pot lipsi;

si punctul zecimal sau 'e' si exponentul (nu simultan) pot

lipsi. Constantele sint in dubla precizie reprezentate.

2. 5. Siruri

Un sir este o secventa de caractere intre ghilimele duble, de

exemplu '' Un sir este de tipul 'tabloul de caractere ' si

in clase de memorare 'static' (vezi &4) si se initializeaza cu

caracterele date. Toate sirurile, chiar daca sint scrise identic,

sint distincte. Compi latorul plaseaza caracterul 0 (byte nul)

la sfirsitul fiecarui sir astfel ca programele care pot detecta

sfirsitul sirului. Intr-un sir, car acterul ' trebuie precedat de

; in plus, secventele deschise pentru constante tip caracter pot

fi folosite. In sfirsit , un si un NL care urmeaza imediat sint

ignorate.

2. 6. Caracteristici hardware

Tabelul care urmeaza rezuma unele proprietati de hardware care

variaza de la masina la masina. Acestea afecteaza

portabilitatea programeleor; in practica aceasta este o problema

care trebuie privita aprioric.

DEC PDP11 HONEYWELL IBM370 INTERDATA8/32

ASCII ASCII EBCDIC ASCII

char 8biti 9 8 8

int 16 36 32 32

short 16 36 16 16

long 32 36 32 32

float 32 36 32 32

double 64 72 64 64

gama reprez. I10-38 I10-38 I10-76 I10-76

+ + +

Pentru aceste patru tipuri de masina, numerele in VF au exponentul

de 8 biti.

3. Notatii sintactice

In manual notatiile sintactice sint scrise cu tipul italic

de caracter cuvintele literale sint caractere tipul drept.

Categoriile alternative sint listate pe linii separate. Un

simbol optional terminal sau nonterminal este indicat prin

subscrierea 'opt', astfel: indica o expresie

optionala intre acolade. Sintaxa este rezumata in $18.

4. Ce este un nume ?

C-ul isi bazeaza interpretarea unui identificator de doua

atribute ale identificatorului: 'clasa de memorare ' si 'tipul'.

Clasa de memorare determina locatia si durata de viata a

unei celule de memorare asociate unui identificator; tipul

determina semnificatia valorii depuse in celula de memorare

a identificatorululilL.

Exista patru clase de memorare declarabile: automatic,

staticexterna si tip registru. Variabilele automatice sint locale

fiecarei apelari a unui bloc (vezi $9. 2) si sint declasate la

iesirea din blocul respectiv. Variabilele statice sint locale unui

bloc, dar retin valoarea pina la revenirea in blocul respecitv

chiar daca controlul a parasit blocul; variabilele exxterne exista

si pastreaza valoarealor in decursul executiei intregului

program si pot sa fie folosite pentru comunicare intre functii

chiar funcctii compilate separat. Variabilele de tip registru

sint numerotate (daca este posibil) in registrii rapizi ai

masinii, ca si variabilele automate sint locale blocului si

dispar la iesirea din bloc.

C suporta citeva tipuri fundamentale de obiecte:

Obiectele declarate ca si caractere (char) sint sufiecient de

mari pentru a sufoca orice membru a setului de caractere

ale implementarii, si daca un caracter pur din acest set de

caractere este sufocat intr-o variabila de tip caracter, valoarea

sa este echivalenta cu codul intreg pentru acel caracter (cu

valoarea intregului care reprezinta caracterul in reprezentarea

interna (NI)) Si alte cantitati pot fi sufocate in variabile tip

caracter, dar implementarea este dependenta de masina.

Sint disponibile 3 dimensiuni de intregi declarati short int, int

si long int. Intregii lungi permit starii mai mari decit cei

scurti, dar implementarea poate face ca intregii scurti, sau

cei lungi, sau ambii sa devina echivalenti cu intregii de baza.

Acestia au dimensiunea naturala decurgind din arhitectura

masinii, celelalte tipuri sint prevazute pentru cerinte speciale.

Intregii fara semn, declarati unsigned se supun legilor

aritmeticii modulo 2n unde n este numarul de bitdin

reprezentare. (La PDP11 cantitatile lungi fara semn nu sint

suportate)

Cantitati in VF simpla (float) sau dubla (double) pot sa fie

sinonime in unele implementari.

Pentru ca cantitatile descrise pot fi interpretate ca numere ce

sint referite ca fiind de tip 'aritmetic'. Tipurile char si int

de toate dimensiunile vor fi in mod colectiv numite de tip

'intreg'. (float si double vor fi denumite de tip 'flotant'.

In afara tipurilor aritmetice de baza exista, conceptual, o clasa

infinita de tipuri derivate din tipurile de baza in modul

urmator:

-tablouri de obiecte de multe tipuri

-functii care dau obiecte de un tip dat

-pointeri la obiecte de un tip dat

-structuri constituind o secvnta de obiecte de tipuri

variate

-marimi capabile sa contina oricare unitate de obiecte de

tipuri varaibie

In general aceste metode de constructie a obiectelor pot fi

aplicate recursiv.

5. Obiecte si lvalori

Un obiect este o regiune manipulabila de memorare; o LVALOARE

este o expresie referitoare la un obiect. Un ex simplu de

expresie LVALOARE este un identificator. Exista operatori

care creaza (produc) lvalori: de ex, daca E este o expresie de

tipul pointer, atunci *E este o expresie lvaloare

referitoare la obiectul spre care pointeaza E. Numele

'lvaloare' vine de la expresia de asignare E1=E2 in care operandul

sting E1 trebuie sa fie o expresie 'lvaloare'. Discutarea, mai

jos, a fiecarui operator indica cind se asteapta operanzi

'lvaloare ' si cind operatorul produce o 'lvaloare'.

6. Conversii

Un numar de operatori depinzind de operanzii lor sa cauzeze

conversia unei valori a operandului dintr-un tip in altul. Aceasta

sectiune explica rezultatul care se asteapta in urma unei

astfel de conversii; &6. 6 rezuma conversiile cerute de

majoritatea operatiilor curente (ordinare N. T) tabloul va

fi imbogatit dupa (prin) discutarea fiecarui operator.

6. 1. Caractere si intregi

Un caracter sau un intreg scurt pot fi folosite oriunde un

intreg se poate folosi. In toate cazurile valoarea este

convertita intr-un intreg. Conversia unui intreg scurt intr-unul

lung implica o extensie de semn; intregii sint cantitati cu

semn. Extensia de semn pt caractere depinde de masina, dar se

garanteaza ca un membru al unui set de caractere standard este ne-

negativ. Dintre masinile discutate aici dar la PDP-11 se extinde

semnul. La PDP-11 valoarea variabilelor tip caracter este in

gama -128 la +127; caracterele alfabetului ASCII sint

toate pozitive. O constanta tip caracter specificata octal sufera

o extensie de semn si poate apare negativa de exemplu '377' are

valoarea -1.

Cind un intreg mai lung este convertit intr-unul mai scurt sau

char el este trunchiat la stinga; bitii in exces sint deplasati

(pierduti).

6. 2. Float si double

Toata aritmetica in C este realizata in dubla precizie; cind

apare un float intr-o expresie el este 'lungit' (extins) in

double prin introducere de zeroruri in partea sa fractionara.

Cind un double este convertit in float, de exemplu printr-o

asignare, double-ul este rotunjit inaintea de trunchiere pe

lungimea unui float.

6. 3. Flotante si intregi

Conversia unei valori flotante in tip intreg devine dependenta

de masina in particular directia de trunchiere a numerelor

negative variaza de la masina la masina. Rezultatul este

nedefibnit daca valoarea nu incape in spatiul prevazut (N. T. pt

un intreg). Conversiile din intreg in flotant sint realizate bine.

Poate apare o pierdere a preciziei daca detinatia nu are un numar

suficient de biti.

6. 4. Pointeri si intreg

Un intreg sau un intreg lung poate fi adunat sau scazut dintr-

un pointer; in acest caz primul este convertit asa cum se

specifica la operatia de adunare. Doi pointeri la obiecte de

acelasi tip pot fi scazuti; in acest caz rezultatul este convertit

intr-un intreg asa cum se va discuta la operatia de scadere.

6. 5. Fara semn

Oridecite ori un intreg fara semn si un intreg normal (de

baza tipic) sint combinati, intregul tip este convertit in intreg

fara semn si rezultatul va fi fara semn. Valoarea este cel mai

mic intreg fara semn congruent intregului cu semn ( modulo2 si

lungimea caracterului). In reprezentarea in complement fata de 2,

conversia este conceptuala si nu se modifica tabloul

(distributia) bitilor. Cind un intreg fara semn este

convertit in long , valoarea rezultatului este aceasi

numeric, ca si a intregului fara semn. Deci conversia este

introducere de zerouri spre stinga.

6. 6. Conversii aritmetice

Multi operatori cauzeaza conversii si produc rezultate de un

tip oarecare, intr-un mod similar. Acest model va fi numit

'conversii aritmetice uzuale'. Intii, oricare operand de tipul

char sau short va fi convertit in int, iar oricare operand de

tipul float este convertit in tipul double.

Apoi, daca un operand este de tip double, atunci si celalalt este

convertit in double si acesta va fi tipul rezultatului. Astfel

daca un operand este long, celalalt este convertit in long si

acesta va fi tipul rezultatului. Astfel, daca un operand este

unsigned, celalalt este convertit in unsigned si acesta va fi

tipul rezultatului. Astfel, daca ambii operanzi sint int, acesta

va fi tipul rezultatului.

7. Expresii

Precedenta (prioritatea ) operatorilor din expresii este

aceasi cu ordinea subsectiunilor din aceasta sectiune,

priritatea maxima fiind prima daca de exemplu expresiile referite

ca operatori pentru +(&74) sint expresiile defiite in &&7. 1-7.

3. In fiecare subsectiune operatorii au aceeasi precedeta.

Asociativitatea la stinga sau la dreapta este specificata in

fiecare din operatorii din operatorii discutati in cadrul

subsectiunii. Precedenta si asociativitatea tuturor operatorilor

din expresii este rezumata in gramatica din &18.

Astfel ordinea de evaluare a expresiilor este nedefinita.

In particular compilatorul se considera liber de a calcula

subexpresiile de maniera pe care el o considera cea mai

eficienta, chiar daca subexpresiile pot conduce la efecte

secundare. Ordinea de aparatie a efectelor secundare este

nespecificata. Expresiile care contin un comutator comutaiv si

asociativ (*, +, &, |, ^) pot fi rearanjate arbitrar, chiar in

prezenta parantezelor, pentru a se forta ordine particulara de

evaluare o explicitare temporara devine necesara.

Prelucrarea depasirilor superioare si verficarea impartirilor

la evaluarea expresiilor este dependenta de masina. Toate

implementarile C-ului ignora depasirile superioare intregi;

prelucrarea impartirii cu 0, si toate exceptiile VF variaza intre

masini si sint uzual ajustabile printr-o functie de biblioteca.

7. 1 Expresii primare

Expresiile primare care contin., ->, subscrieri, si apeluri

de functii se grupeaza de la stinga la dreapta.

primary-expresion:

identifier

constant

string

(expresion)

primary-expresion[expresion]

primary-expresion(expresion-list opt)

primary-lvalue. identifier

primary-expresion->identifier

expresion-list:

expresion

expresion-list, expresion

Un idetificator este o expresie primara, cu garantia ca a fost

declarat asa cum se va discuta. Tipul sau este

specificat la declarare. Daca tipul idetificatorului este

'tablouri de' atunci valoarea expresiei

identificatorului sau este un pointer la primul obiect din

tablou, iar tipul expresiei este 'pointer la'. Mai mult, un

idetificator de tablou (masiv) nu este o lvaloare. La fel un

idetificator care e declarat 'function returning' (functie

care returneaza ), cind este folosit (cu exceptia cazului cind

apare ca numele functiei la un apel) este convertit in

'pointer la functia ce returneaza'.

O constanta este o expresie primara. Tipul ei poate fi int,

long sau double, depinzind de forma sa. Constantele tip

caracter au tipul int; constantele flotante sint double.

Un sir este o expresie primara. Tipul sau original (la origine)

este 'tablou de char'; urmind insa aceeasi regula data

pentru identificatori, acesta este modificat in 'pointeri catre

char' si rezultatul este un pointer catre primul caracter al

sirului (exista o exceptie pt unele initializari a se vedea

&8.6.).

O exprsie in paranteze este expresie primara a carui tip si

valoare sint identice cu ale expresiei fara paranteze.

Prezenta parantezelor nu are implicari daca expresia este o

lvaloare. O expresie primara urmata de o expresie in

paranteze drepte este o expresie primara. Sensul intuitiv este

acela al unui indice. Obisnuit expresia primara are tipul

'pointer catre', expresia indicelui este int, iar tipul

rezultatului este '' (!!! N. T. ). Expresia E1[E2] este

identica (prin definitie) cu *((E1)+(E2)). Toate reguluile

necesare intielegerii acesteinotatii sint continute in

aceasta sectiune impreuna cu discutiile din &&7. 1, 7. 2 si 7.

4. asupra identificatorilor, *, si respectiv +; &14. 3 rezuma

implicatiile.

Un apel de functie este expresie primara urmata de

paranteze continid un posibil vid, o lista de expresii separate

prin virgule constituind argumentele actuale ale functiei.

EXpresia primara trebuie sa fie de tipul 'functie care

returneaza', si rezultatul apelului functiei este de tipul

''. Cum se va indica, un identificator nevazut urmat de o

paranteza stinga este contextual declarat ca reprezentind o

functie care returneaza un intreg; deci in majoritatea

cazurilor functiile car dau ca rezultat o valore intreaga nu

trebuie declarate.

Orice argument actual de tipul float este convertit in double

inainte de apel; oricare argument de tipul char sau short

este convertit in int; si, ca deobiecei numele de tablouri

sint convertit in pointere. Daca este necesara o conversie se va

folosi (N. T. cast) vezi &7. 2, 8. 7.

La pregatirea unui

apel la o functie se face o copie a fiecarui parametru actual

adica toate trecerile de argumente in C se fac prin valoare. O

functie poate modifica valorea parametrilor sai formali, dar

aceste modificari nu acteaza valoarea parametrilor actuali !Mai

mult se poate trece un pointer cu subintelesul functia poate

modifica valoarea obiectului spre care pointerul indica. Un

nume de tablou este o expresie pointer. Ordinea de evaluare a

argumentelor este nedefinita de catre limbaj;a se nota ca

difera de la compiler la compiler. Sint permise apeluri recursive

la orice functie. O expresie primara urmata de un punct

urmat de un identificator este o expresie. Prima expresie

trebuie sa fie o lvaloare un signed a structurii sau o reuniune

iar identificatorul trebuie sa fie un membru a structurii

sau reuniunii. Rezultatul este o lvaloare referind membrul numit

al structurii sau reuniunii.

O expresie primara urmata de o sageata (care se construieste din

-si >) urmata de un identificator este oexpresie. Prima expresie

trebuie sa fie un pointer la o structura sau la o reuniune si

identificatorul trebuie sa numeasca un membru al acelei

structuri sau reuniuni. Rezultatul este lvaloare care

refereaza membrul numit al structurii sau reuniunii catre

care pointerul expresiei puncteaza.

Astfel <expresia E1->MOS este identica cu (*E1). MOS. Structurile

si reuniunile se discuta in &8. 5. Regulile date aici pentru

utilizarea structurilor si reuniunilor nu nu sint stricte, de

maniera care permite sa se scape de mecanismul tipurilor. Vezi

&14.1.

7. 2. Operatori unari

Expresiile cu operatori unari se grupeaza de la dreapta la stinga.

unary-expression:

*expression

&lvalue

-expression

!expression

-expression

++lvalue

--lvalue

lvalue++

lvalue--

(type-name)expression

sizeof expression

sizeof(type-name)

Operatorul * inseamna indirect: expresia trebuie sa fie un

pointer si rezultatul este o lvaloare care se refera la

obiectul spre care pointeaza expresia. Daca tipul unei expresii

este 'pointer catre' tipul rezultatului este ''.

Rezultatul operatiei & este un pointer catre obiectul referit

prin lvaloare. Daca tipul lvalorii este ' ' tipul rezultatului

este 'pointer catre'.

Rezultatul unei operatii este negarea operandului. Se

realizeaza conversiile aritmetice obisnuite. Negativul unei

cantitati este calculat prin scaderea valorii sale din 2 la n

, unde 'n' este nr de biti pe care se reprezinta un int. Nu exista

operatorul unar +.

Rezultatul operatiei de negare logica ! este 1 daca valorea

operandului a fost 0, si 0 daca operandul este non-zero. Tipul

rezultatului este int. Operatia este aplicabila oricarui tip de

opernand aritmetic sau pointerilor.

Obiectul referit prin operandul lvaloare precedat de ++ este

incrementat. Valoarea este noua valoare a operandului dar nu

este o lvaloare. Expresia ++x este echivalenta cu x+=1. A se vedea

adunarea (&7. 4) si operatorii de asignare (&7. 14) pentru

informatii asupra conversiilor.

Operandul lvalorii cu prefixul -- este decrementat analog cu ++.

Cind postfixul ++ este aplicat unei lvalori rezultatul este

valorea obiectului referit pr in lvaloarea. Dupa ce

rezultatul este notat obiectul este incrementat in

aceeasi maniera ca pentru operatorul prefix++. Tipul

rezultatului este acelasi cu tipul expresiei lvaloare.

Cind postfixul -- este aplicat unei lvalori rezultatul este

valoarea obiectului referit prin lvaloare. Dupa notarea

rezultatului obiectul este decrementat in maniera prefixului --.

Tipul rezultatului este acelasi cu tipul expresiei lvaloare.

O expresie precedata de un nume de tip de data in paranteze

cauzeaza conversia valorii expresiei in tipul de data numit

constructia este denumita un cast (rol distributie, ). Numele

de tipuri de date sint descrise in &8. 7.

Operatorul sizeof produce marimea in bytes a opeandului sau. (Un

byte nu este definit de limbaj decit in termenul de valore a

lui sizeof). Dar in toate implementarile un byte este spatiul

necesar pastrarii unui char. Aplicat unui tablou rezultatul este

numarul total de bytes din tablou. Marimea se determina din

declaratiile obiectelor in expresii. Expresia este semnatic o

constanta intreaga si poate fi folosita oriunde este necesara o

constanta. Se foloseste la comunicarile cu subprograme ca

alocatori de memorie si sisteme de //0.

Operatorul sizeof poate fi aplicat unui nume de tip de data in

paranteze. In acest caz va da marimea in bytes, a unui obiect de

tipul indicat.

Constructia sizeof (type) este 1 deci expresia sizeof(type) -2

este aceeasi cu (sizeof(type)) -2.

7. 3. Operatori de inmultire

Operatorii de inmultire *, /, % grupeaza de la stinga la dreapta.

Se realizeaza conversiile aritmetice uzuale.

multiplicative-expression:

expression*expression

expression/expression

expression%expression

Operatorul binar* indica inmultire. Operatorul * este asociativ

si expresiile cu mai multe inmultiri de acelasi nivel pot fi

rearanjate de compilator.

Operatorul /indica impartire. Cind se impart intregi

pozitivi se face o trunchiere spre 0, dar forma trunchierii

este dependenta de masina daca unul din operanzi este negativ.

Pe toate masinile discutate in acest manual restul are semnul

impartitorului. Todeauna este adevarat ca (a/b) *b+a%b este egal

cu a (daca b e diferit de zero).

Operatorul % produce restul impartirii primei expresii la a doua.

Se realizeaza conversiile aritmetice uzuale. Operanzii trebuie sa

nu fie float.

7. 4. Operatori aditivi

Operatorii aditivi + si- grupeaza de la stinga la dreapta.

Se realizeaza conversiile aritmetice uzuale. Exista citeva

posibilitati de tip aditionale pentru fiecare operator.

aditive-expression:

expression+expression

expression-expression

Rezultatul operatiei + este suma operanzilor. Un pointer

catre un obiect dintr-un tablou si o valare de orice tip intreg

pot fi adunate. Ultima este in toate cazurile convertita intr-un

deplasament de adresa (N. T. address offset) prin inmultirea cu

lungimea obiectului spre care indica pointerul. Rezultatul este

un pointer de acelasi tip cu pointerul original si care indica

un alt obiect din acelasi tablou, corespunzator deplasat fata

de obiectul original. Deci daca P este un pointer catre un

pointer dintr-un tablou (N. T. array) expresia P+1 este un pointer

catre urmatorul element (obiect) din tablou.

Nu este permisa o alta forma de combinatie de tipuri pentru pointeri.

Operatorul + este asociativ si expresiile cu adunari multiple la

acelasi nivel pot fi rearanjate de compiler. Rezultatul

operatorului - este difernta dintre operanzi. Se realizeaza

conversi aritmetice uzuale. In plus o valore de orice tip de

intreg poate fi scazuta dintr-un pointer cu aceeasi conversie ca

la adunare.

Daca doi pointeri catre obicte de acelasi tablou sint scazuti

rezultatul este convertit (prin impartire cu lungimea

obiectlui) intr-un int care reprezinta numarul de obicte care

separa obictele indicate (pointed-to). Conversia poate da

rezultate neasteptate, daca pointerii nu indica oectele

aceluiasi tablou intrucit pointerii chiar spre obiecte de

acelasi tip nu difera printr-un multiplu al lungimii obiectelor.

7. 5. Operatori de deplasare

Operatorii de deplasare << si >> grupeaza stinga la

dreapta. Ambii fac conversiile uzuale asupra operanzilor fiecare

trebuind sa fie un intreg. Apoi operandul din dreapta se

cponverteste in int; tipul rezultatului este aceea al operandului

din stinga. Rezultatul este nedefinit daca operandul din dreapta

este negativ sau > sau = cu lungimea obiectului in biti.

shift-expression:

expression<<expression

expression>>expression

Valoarea lui E1<<E2 este E1 (interpretat ca forma de biti)

deplasat la stinga; biti eliminati sint umpluti cu zero.

Valoarea lui E1>>E2 este E1 deplasat dreapta cu E2 pozitii

binare. Deplasarea la dreapta este garantat a fi logica (cu

umplere de zerouri) daca E1 nu are semn; altfel poate fi (si este

la PDP11) aritmetica (cu umplerea bitului semn).

7. 6. Operatori relationali

Operatorii relationali grupeaza stinga la dreapta dar acest fapt

nu este foarte folositor; a<b<c nu inseamna ceea ce pare.

relational-expression:

expression<expression

expression>expression

expression<=expression

expression>=expression

Operatorii <, >, <=, >= dau 0 daca relatia este falsa si 1 daca

este adevarata. Tipul rezultatului este int. Se fac

conversiile uzuale. Doi pointeri se pot compara rezultatul

depinde de locatiile relative in spatiul de adrese a

obiectelor poinate. Comparatia pointerilor este portabila numai

cind pointerii indica spre obiecte din acelasi tablou.

7. 7. Operatori de egalitate

equality-expression:

expression==expression

expression!=expression

Semnul == (egal cu) si !=(inegal cu ) sint analogi operatorilor

relationali dar nu au prioritate mai mica. (adica a<b==c<d

este 1 daca a<b si c<d au valoare adevarat).

Un pointer poate fi comparat cu un intreg dar rezultatul va fi

dependent de masina. Cu exceptia cazului cind intregul este

constanta 0. Un pointer caruia i s-a asigurat valorea 0 se

garanteaza ca nu va pointa spre nici un obiect si va apare a fi

egal cu 0;in utilizarea conventionala un astfel de pointer este

considerat nul.

7. 8. Operatorii si pe biti:

and expression:

expression&expresion

operatorul & este asociativ si expresiile continind & pot fi

rearanjate Se realizeaza conversiile aritmetice uzuale; rezultatul

este functia SI pe biti, a celor doi operanzi. Operatorul se

aplica numai operanzilor intregi.

7. 9. Operatorul sau exclusiv pe biti

exclusive-or-expression:

expression^expression

Operatorul ^ este asociativ si expresiile care contin ^ pot fi

rearanjate. Se realizeaza conversiile aritmetice uzuale;

rezultatul este SAU exclusiv al celor doi operanzi la nivel de

bit. Operatorul se aplica doar operanzilor intregi.

7. 10 Operatorul sau inclusiv

inclusiv-or-expression:

expression|expression

Operatorul | este asociativ expresiile care-l contin pot fi

rearanjate. Se realizeaza conversii aritmetice uzuale; rezultatul

este functie SAU inclusiv a operanzilor la nivel de bit.

Operatorul se aplica doar operanzilor intregi.

7. 11. Operatorul si logic

logical-and-expression:

expression&&expression

Operatorul && grupeaza de la stinga la dreapta. El da 1 daca

ambii operanzi sint diferiti de 0 altfel da 0. Nu ca &, &&

garanteaza o evaluare de la stinga la dreapta; al doilea operand

nu este evaluat daca primul este egal cu 0.

Operanzii pot fi de tipuri diferite dar fiecare trebuie sa

fie unul din tipurile fundamentale sau un pointer. Rezultatul este

intodeauna int.

7. 12 Operatorul sau logic

logical-or-expression:

expression||expression

Operatorul || opereaza de la stinga la dreapta. El da 1 daca unul

din operanzi este diferit de 0 si altfel da 0. Nu ca |, ||

face evaluare la stinga -> dreapta, al doilea operand nu mai este

evaluat daca primul este diferit de 0.

Operanzii pot fi de tipuri diferite dar de tipurile de baza

(fundamentale) sau pointeri. Rezultatul este totdeauna int.

7. 13 Operator conditional

conditional-expression:

expression?expression:expression

opereaza de la dreaptspre stinga. Prima expresie este evaluata si

daca este non zero rezultatul este valoarea celei de a doua

expresii. Altfel este al celei dea treia expresii. Daca este

posibil conversiile artimetice uzuale se fac pentru a aduce a

doua si a treia expresie la un tip comun; se poate ca unul sa fie

pointer si celalat zero, si rezultatul are tipul

pointerului. Numai expresiile a doua si a treia sint evaluate.

7. 14. Operatori de atribuire

Operatorii de atribuire opereaza de la dreapta spre stinga.

Toate solicita o lvaloare ca opernd stinga, iar tipul unei

expesii de asigurare este acela al operandului din stinga.

Valoarea este valoarea stocata in operandul din stinga dupa ce

asigurarea s-a facut. Cele doua parti ale unui operator de

asigurare compus sint elemente sintactice (atomi)separati.

assignement-expression:

lvalue=expression

lvalue+=expression

lvalue-=expression

lvalue*=expression

lvalue/=expression

lvalue%=expression

lvalue>>=expression

lvalue<<=expression

lvalue&=expression

lvalue^=expression

lvalue|=expression

La asigurarea simpla cu = valoarea expresiei inlocuieste pe cea a

obiectului referit prin lvaloare. Daca ambii operanzi sint de

tip aritmetic operandul drept se converteste in tipul celui sting

inainte de asigurare.

Comportarea unei expresii dforma E1op=E2 poate fi inferred luind

ca echivalent al ei E1=E1op(E2); oricum E1 este evaluata doar

odata. La += si -= operandul sting poate fi un poninter in

care opernadul din dreapta (intreg) este convertit dupa cum

se explica in &7. 4; toti opernazii din dreapta si toti opernazii

stingi non pointeri trebuie sa fie de tip aritmetic.

Compilatoarele permit ca un pointer sa fie asignat unui intreg,

un intreg sa fie asignat unui pointer si un pointer sa fie asignat

unui pointer de alt tip. Asignarea este operatia de copiere pura

fara conversii. Aceasta utilizare este neportabila si poate

produce pointeri care pot cauza exceptii de adresare la utilizare.

Este garantata asignarea constantei zero la un pointer aceasta

producind un pointer nul distinct de orice pointer spre orice

obiect.

7. 15 Operatorul virgula

comunn-expression:

expression, expression

O pereche de expresii separate prin virgula este evaluata de

la stinga la dreapta si valorea expresiei din stinga este

declasata. Tipul si valoarea rezultatului sint tipul si

valorea operandului din dreapta. Operatorul lucreaza de la

stinga la dreapta. In contextul unde virgulei i se da un inteles

special, de exemplu intr-o lista de argumente pt o fc. (&7. 1)

sau liste de initializare (&8. 6), operatorul - virgula

descrisa aici poate apare doar in paranteze, de exemplu:

f(a, (t=3, t+2), c)

are trei argumente, al doilea avind valoarea 5.

CAPITOLUL 8. Declaratii

Declaratiile sint folosite pt a specifica interpretarea pe care C

o da fiecarui identificator; nu fac in mod necesar si

rezervarea de memorie pt respectivul identificator. Declaratiile

au forma:

declaration:

decl-specifiers declarator-list opt;

Declaratorii din lista de declaratori contin identificatorii

de declarat. Specificatorii de declaratii constituie o secventa

de specificatori de tip si clase de memorare:

decl-specifiers:

type-specifier decl-specifiers opt

sc-specifier decl-specifiers opt

lista trebuie sa fie unica (self consistent) in exemplul

descris mai jos. (N.T. -sc=storage class)

8. 1. Specificatori de clase de memorare

Acestia sint:

sc-specifier:

auto

static

extern

register

typedef

specificatorul 'typedef' nu rezerva memorie si este numit

'specificator' de clasa de memorie ' doar din motive

sintactice; se diacuta la &8. 8 sensurile diverselor claselor de

memorare s-au discutat in &4.

Declaratiile auto, static si register servesc ca definitii pt

ca cauzeaza o rezervare de memorie. La extern trebuie sa existe o

definire externa (vezi &10) pt identificatori dati undeva in afara

functiei unde ei au fost declarati.

Declaratia register este mai des vazuta ca o declaratie auto

impreuna cu o alertare a compilatorului ca aceste varaibile vor fi

utilizate des. Doar citeva declaratii de acest tip sint

efective. Mai mult doar varaibilele de anumite tipuri vor fi

stocate in registre; la PDP11 acestea sint int, char si pointeri.

O alta restrictie se refera la variabilele registru.

Operatorul & (care lucreaza cu adrese) nu li se poate aplica

programele create pot deveni mai mici mai rapide dintr-o utilizare

de declaratii register folosite corespunzator, dar inbunatatiri

viitoare lae generarii de cod pot sa le faca necesare.

Cel putin un specificator de tip memorare poate fi dat intr-o

declarare. Daca lipseste el este considerat auto in interiorul

functiei, si extern in afara ei. Exceptie: functiile nu sint

niciodata automatic.

8. 2. Specificatori de tip

type-specifier:

char

short

int

long

unsigned

float

double

struct-or-union-specifier

typedef-name.

Cuvintele long, short si unsigned pot fi privite ca si

adjective; urmatoarele combinatii sint aceptabile.

short int

long int

unsigned int

long float

Sensul ultimei constructii este acelasi cu double. Altfel

cel mult un specificator de tip poate fi dat intr-o declaratie.

Daca specificatorul de tip lipseste el este considerat int.

Specificatorii de structuri si reuniuni vor fi discutati in &8. 5,

declaratiile cu typedef sint discutate in &8. 8.

8. 3. Declaratori

Lista de declaratori care apare intr-o declaratie este o secventa

separata prin virgula de declaratori, fiecare trebuind sa aiba o

initializare.

declarator-list:

init-declarator

init-declarator, declarator-list

int-declarator:

declarator initialiser opt.

Initializatorii sint discutati in &8. 6. Specificatorii dintr-

o declarattie indica tipuri si clase de memorare a

obiectelor la care se refera declaratorii. Declaratorii au

sintaxa:

declarator:

identifier

(declarator)

*declarator

declarator()

declarator[constant-expression opt]

Gruparea este ca la expresii.

8. 4. Sensul declarartorilor

Fiecare declarator este o afirmatie de genul ca atunci cind o

constructie de aceeasi forma ca si declaratorul apare intr-o

expresie, va produce un obiect de tipul si clasa indicata. Fiecare

declarator contine doar un identificator;acest identificator se

declara.

Daca doar un identificator apare ca declarator, atunci el va avea

tipul indicat de specificatorul de la inceputul declaratiei.

Un declarator in paranteze este identic cu un declarator fara

atribute, dar amestecarea declaratorilor complecsi poate fi

alterat prin paranteze. Vezi exemplele de declaratie.

Acum sa ne imaginam o declaratie

T D1

unde T este un specificator de tip (ca int) si D1 este un

declarator. Sa presupunem ca aceasta declaratie face ca

identificatorul (N. T. din declarator) sa aibe tipul ''unde '

' este gol daca D1 este doar un identificator pur si sipmplu (asa

ca tipul lui X din 'int X' este doar int ). Daca D1 are forma:

*D

tipul identificatorului continut este 'pointer la T'.

Daca D1 are forma

D()

atunci identificatorul continut are tipul ' functie ce

returneaza T. '

Daca D1 are forma D[constant-expression] sau D[], atunci

identificatorul continut are tipul 'tablou de T'. In primul

caz expresia constantei este o expresie a carei valoare este

determinabila in momentul compilarii si care are tipul int

(expresiile constanta sint definite precis in &15). Cind mai

multe specificatii de tsblou sint adiacente se creaza un

tablou multidimensional; expresiile constanta care specifica

limitele tablourilor pot sa lipseasca doar pentru primul membru al

secventei. Aceasta forama este folositoare daca tabloul e extern

si definitia actuala, care aloca spatiu, este totusi data.

Prima expresie contanta poate fi omisa daca declaratorul

este urmat de o initializare. In acest caz marimea se

calculeaza din nr elemente precizate.

Un tablou poate fi constituit din unul din tipurile de baza

prin pointeri dintr-o structura sau reuniune, sau din alt

tablou (pt a genera tablouri cu dimensiuni multiple).

Nu toate posibilitatile date de sintaxa sint permise.

Restrictiile sint urmatoarele: functiile nu pot returna tablouri,

structuri sau reuniuni dar pot returna pointeri spre asa ce va;

nu exista tablouri de functii dar pot exista tablouri de pointeri

spre functii. O structura sau o reuniune nu poate contine o

functie, dar poate contine un pointer la o functie. Exemple:

int i; *ip, f(), *fip(), (*pfi)();

decalara

un intreg i

un pointer ip la un intreg

o functie f care returneza un intreg

o functie fip care returneaza un pointer la un intreg

un pointer pfi la o functie care reurneaza un intreg

Se compara ultimele. *fip() este *(fip()) declaratia

sugereaza si aceiasi constructie intr-o expresie necesita apelul

functiei fip si apoi indirectarea spre rezultat (pointer) se

produce un intreg. (*pfi)() in declaratie parantezele sint

necesare ca si intr-o expresie ca sa indice ca indirectarea prin

pointeri la o functie produce o functie care este apoi chemata; va

returna un intreg.

Alt exemplu:

float fa[17], *afp[17]

declara un tablou de flotante si un tablou de pointere spre numere

flotante.

In final:

static int x3d[3][5][7];

declara un tablou de intregi, static, cu dimensiunile 3x5x7.

In detaliu X3d este un tablou de 3 articole; fiecare articol este

un tablou de 5 tablouri; si fiecare din ultimul este un tablou

de 7 intregi. Oricare din expresiile x3d, x3d[i], x3d[i][j],

x3d[i][j][k] poate apare intr-o expresie. Primele trei sint de tip

'tablou', ultima are tipul int.

8. 5. Declaratorii de structuri si reuniuni

O structura este un obiect constind dintr-o secventa de

memorii cu nume. Fiecare membru poate avea orice tip. O

reuniune este un obiect care, la un moment dat, poate contine pe

oricare din mai multi membri.

Specificatorii de structuri si reuniuni au aceeasi forma:

struct-or-union-specifier:

struct-or-union

struct-or-union identifier

union identifier

declara identificatorul ca eticheta (marcaj) de structura

(sau uniune) a structturii specificate de lista. O declaratie de a

treia forma

struct identifier

union identifier

Etichetele de structura permit definirea de structuri auto-

referibile ele permit ca partea lunga a unei structuri sa fie

data odata si folosita de mai multe ori. Este ilegal a declara

o structura sau uniune care face apel la ea insasi, dar o

structura sau uniune poate contine un pointer la un apel spre ea

insasi.

Numele membrilor si etichetele sint la fel ca pentru variabilele

ordinare dar sa fie distincte mutual.

Doua structuri pot folosi in comun o secventa initiala de membri;

adica acelasi membru apare in doua structuri diferite daca au

acelasi tip in ambele si daca membrii anteriori sint acesasi

in ambele(In momentul de fata, compilatorul verfica numai daca

in unul din doua structuri diferite are acelasi tip si

deplasament in ambele, dar daca membrii precedenti difera,

constructtia este neportabila ).

Exemplu simplu de declarare de structura:

struct tnode;

contine

-un tablou de 20 caractere

-un intreg

-2 pointeri catre structuri similare

Odata aceasta declaratie facuta, declaratia

struct tnode s, *sp;

declara S ca fiind o structura de tipul dat si sp un pointer

la o structura de tipul dat.

Cu aceste declaratii expresia:

sp->count

Se refera la cimpul count spre care pointeaza sp;

s. left

Se refera la pointerul subarborelui stinga

s. right->tword[0]

Se refera la primul caracter al subarborelui tword din arborelui

drept al lui S.

8. 6. Initializare

Un declarator poate specifica o valoare initiala pt

identificatorul declarat. Initializatorul este precedat de = si

consta dintr-o expresie sau o lista de valori in acolade.

initializer:

=expression

=

=

initializer-list:

expression

initializer-list, initializer-list

Toate expresiile pentru initializarea unei variabile statice

sau externe trebuie sa fie expresii de constanta, descrise in

&15, sau expresii care se reduc la adresa variabilei declarate

anterior, cu posibilitatea de a fi deplasate printr-o

constanta. Variabila automatic si register pot fi

initializate cu expresii arbitrare care pot contine

constante, variabile declarate anterior si functii.

Variabilele statice si externe neinitializate la start primesc

valoarea zero. Cele automatic si register au continut nespecificat

(probabil 'gunoi').

Cind intr-un initializator se aplica unui scalar (pointer sau un

obiect de tip aritmetic) el consta din expresie singulara

posibil in paranteze. Valoarea initiala a obiectului se obtine

din expresie; aceleasi conversii ca pentru atribuire se folosesc.

Cind o variabila declarata este un agregat ( structura sau

tablou) atunci initializatorul consta dintr-o lista de

initailizatori separati prin virgule in parantze (acolade) scri

si in dinea in care cresc indicii sau in orinea membrilor.

Daca numarul de initializatori este mai mic decit al membrilor

se impune restul cu 0. Nu se initializeaza uniuni sau agregate de

tip automatic.

Acoladele se pot elimina. Daca un initilizator incepe cu acolade

stinga atunci va urma o lista de initializare cu

initializatori despartiti stinga prin virgule pentru membrii

agregatului; este eronat sa existe mai multi initializatori

decit membri. Daca initializatorul nu incepe cu acolada stinga

atunci se iau din lista numarul necesar de elemente pentru

agregatul curent, restul lasati la dispozitia agrgatului urmator.

De exemplu:

int x[]=;

x este declarat si initializat cu un tablou cu o dimensiune

care are trei membri.

float y[4][3]={

, initializeaza prima linie adica y(0)

, care este y[0][0], y[0][1] si y[0, 2]

, apoi se initializeaza liniile y[1] si y[2]

}; y[3] se inittializeaza cu 0.

Acelasi efect se obtine cu:

float y[4][3]=;

Initializarea pentru y incepe cu acolada stinga, dar pentru y[0]

nu, de ci se folosesc trei elemente din lista. Urmatorele trei

sint luate pentru y[1] si y[2]. Deci:

float y[4][3]=, , ,

};

initializeaza prima coloana a lui y (privit ca un tablou cu

doua dimensiuni) si lasa restul pe zero.

Si:

char msg[]='syntax error on line %s/n';

arata un tablou de caractere a carui membri sint initializati cu

un sir.

8. 7. Nume de tipuri

In doua contexte (pt a se specifica explicit o expresie cu

ajutorul unei distributii (N. T. cast) si ca si argument pt

size of) este de dorit a se specifica numele unui tip de data.

Aceasta se realizeaza folosind 'nume de tip' care este in

esenta o declaratie pt un obiect de tipul respectiv care omite

numele obiectului.

type-name:

type-specifier abstract-declarator.

abstract-declarator:

empty

(abstract-declarator)

*abstract-declarator

abstract-declarator()

abstract-declarator[constant-expression opt]

Pentru a se evita ambiguitatea in constructia

(abstract-declarator),

abstract-declaratorul nu trebuie sa fie vid. Cu aceasta

restrictie se poate identifica unic locatia din abstract-

declarator unde va apare declaratorul daca constructia a fost un

declarator intr-o declaratie. Tipul de nume este acelasi cu tipul

unui identificator ipotetic de exemplu:

int tip->intreg

int* pointer la (catre) intreg

int*[3] tablou de 3 pointeri la intregi

int(*)[3] pointer la un tablou format din 3 intregi

int*() functie care returneaza un pointer la un intreg

int(*)() pointer la o functie care returneaza un intreg

8. 8. Typedef

Declaratiile a caror 'clasa de memorare' este typedef nu definesc

o memorie ci definesc identificatori care vor fi utilizati

ulterior ca si cum ar fi cuvinte cheie de tip denumind tipuri

fundamentale sau derivate.

typedef-name:

identifier

Rorul unei declaratii continind typedef este ca orice

identificator care apare ca parte a oricarui declarator din

interiorul (declaratiei) devine sintactic echivalenta cu cuvintele

cheie de tip numind cuvintele de tip asociat identificatorului in

modul desis in &8..De exemplu, dupa:

typedef int MILES, *KLICKSP;

typedef structcomplex;

Constructiile

MILES distance;

extern KLICKSP metricp;

complex 2, *zp;

sint declaratii legale; tipul lui distance este int, al lui

metricp este 'pointer la un int', si al lui z este structura

specificata; zp este pointer la respectiva structura.

typedef nu introduce tipuri noi, numai sinonime pt tipuri care se

pot specifica si altfel. In exemplul distance este considerat

a avea exact acelasi tip ca orice alt obiect int.

9. Enunturi

Cu exceptiile ce vor fi indicate, enunturile se executa in

secventa.

9. 1. Enunt expresie

Multe enunturi sint enunturi expresie, care au forma:

expression;

In general enunturile expresie sint asignari sau apeluri de

functie.

9. 2. Enuntul compus sau block

Se prevede enuntul compus intrucit se pot folosi mai multe

enunturi acolo unde este asteptat doar unul:

compound-statement;

declaration-list:

declaration

declaration, declaration-list

statement-list

statement

statement statement-list

Daca unul din identificatorii din lista de declaratii a fost

declarat anterior, declaratia externa este decazuta pentru

durata unui bloc, dupa care isi epuizeaza forta.

Orice initializare de variabile auto sau register se realizeaza de

fiecare data cind se intra in bloc la virful sau. Este posibil(

dar este o practica rea ) de a face transferul in bloc; in acest

caz nu se face initializarea.

Initializarea variabilelor static se face doar odata, la

inceputul executiei programului. In bloc, declaratiile extern

nu rezerva memorie astfel ca initializarea nu este permisa.

9. 3. Enunturi conditionale

Sint 2 forme de enunturi conditionale:

if(expresie) statement

if(expresie) statement else statement

In ambele cazuri se evalueaza expresia si daca nu sint zero se

executa primul enunt. In al 2-lea caz se executa a 2-a

instructie daca prima este egala cu zero. Ambiguitatea lui

'else' este rezolvata prin conectarea unui 'else' cu ultimul

'else-less if' intilnit.

9. 4. Instructii while

Forma: while(expression)statement

Instructia din while este executat repetat atita timp cit

valoarea expreie ramine diferita de zero. Testul se face inainte

de executia instructiei.

9. 5. Instructia do

Are forma

do statement while(expression);

Instructia este executata repetat pina cind valorea expresiei

devine zero. Testul se face dupa fiecare executie a instructiei.

9. 6. Instructia for

Are forma:

for(expression-1opt;expression-2opt;expression-3opt)statement

Este echivalenta cu:

expression-1;

while(expression-2)

Deci prima expresie specifica initializarea buclei; a doua

specifica un test, facut inaintea fiecarei iteratii, astfel ca

din bucla se iese cind expresia devine zero; a 3-a expresie

specifica o incrementare care este realizata dupa fiecare

iteratie.

Oricare sau toate expresiile pot lipsi. Daca lipseste a doua

instructie while implicata devine echivalenta cu while(1);

celelalte expresii vor lipsi din constructia data.

9. 7. Instructia switch

Instructia switch face ca controlul sa fie transferat la una

din mai multe instructii functie de valoarea expresiei. Are forma:

switch(expression)statement

Se executa conversiile necesare, dar rezultatul trebuie sa fie

int. Instructia este compusa. Orice instructie din bloc pate

fi etichetata cu un prefix tip case

case constant-expression

unde expresia de constanta va fi un intreg(int). Este interzisa

aparitia a doua constante pentru case in aceasi instructie

switch cu aceeasi valoare. Constantele se definesc precis in

&4. 5.

Poate exista un prefix de instructie de forma

default:

Cind se executa instructia switch, expresia se evalueaza si

se compara cu constantele case. Daca una este egala cu valorea

expresiei, controlul se va da la instructia urmind prefixul gasit.

Daca nu exista instructii cu case-ul cautat, dar exista

prefixul defaault, controlul se da la instructia prefixata.

In lipsa prefixului default nu se executa nici una din

instructiuni.

case si default, in sine, nu altereaza mersul programului.

Iesirea din switch se face cu break (vezi &9. 8) In general

instructia al carui subiect este switch este un bloc.

Declaratii pot apare la inceputul instructiei, dar

initializarea variabilelor automatic si register sint

inefective.

9. 8. Instructia break

Are forma: break; si face sa se termine ciclul cel mai intern

while, do, for sau switch. Controlul trece la instructia care

urmeaza dupa instrucctia de terminare.

9. 9 Instructia continue

Are forma:

continue;

si face sa se treaca la continuarea in bucla a celui mai intern

while, do sau for; adica se sare la sfirsitul buclei. Mai precis,

in fiecare din instructiile

while() do }while(); }

O instrcutie continue este echivalenta cu goto contin(Dupa contin:

o instructie goala)

9. 10. Instructia return

O functie revine la apelant cu instructia return care are formele:

return;

return expression;

In primul caz valoarea returnata nu e definita. In al doilea

caz valoarea expresiei este returnata apelantului. Daca se cere,

expresia este cnvertita, ca la asignare, in timpul functiei in

care apare. Ocolirea finalului unei functii este echivalenta cu

nereturnarea de valoare la apelant.

9. 11. Instructia goto

Controlul se poate transfera neconditionat cu ajutorul instructiei:

goto identifier;

Identificatorul trebuie sa fie o eticheta (vezi 9. 12) din functia

curenta.

9. 12 Instructii etichetate

Oricare instructie poate fi precedata de un prefix eticheta de

forma

identifier:

care serveste pentru declararea identificatorului ca si

eticheta. Unica utilizare a etichetei este de tinta a unui

goto. Bataia unei etichete este functia curenta, excluzind sub

blocurile in care acelasi identificator poate fi redeclarat. Vezi

&11.

9. 13 Instructia nula

Are forma

;

Este folosita pentru ca poate purta o eticheta chiar inainte de

}(N. T. acolada finala) a unei instructii compuse sau servind ca

si corp de instructii nul unei instructii de buclare gen while.

10. Definitii externe

Un program C consta dintr-o secventa de definitii externe. O

definitie externa declara un identificator ca avind clasa de

memorare extern (in lipsa specificatorului sau static,

si un tip specificatn tip specificat. Specificatorul de tip

(vezi 8. 2) poate fi vid, in care caz tipul va fi luat ca si int.

Intinderea unei definitii externe persista pina la sfirsitul

fisierului in care a fost declarata asa cum efectul unei

declaratii persista pina la sfirsitul unui bloc. Sintaxa

defintiilor extern este aceeasi ca a tuturor declaratorilor, cu

exceptia ca numai la acest nivel poate fi dat codul pentru

functii.

10. 1. definitii defunctie externe

Definitiile de functii au forma:

function-definition:

decl-specifiersopt function-declarator function-body

Singurii specificatori de clasa de memorare permisa in cadrul

specificatorilor de declaratii sint extern sau static; a se

vedea &11. 2 pentru distinctia dintre ele. Un declarator de

functie este similar cu un declarator pentru 'functie care

returneaza' cu exceptia ca el listeaza parametrii formali ai

functiei de definit.

function-declarator:

declarator(parameter-listopt)

parameter-list:

identifier

identifier, parameter-list

Corpul functiei are forma:

function-body:

declaration-list compound-statement

Identificatorii din lista de parametrii, si numai acesti

identificatori, pot fi declarati in lista de declaratii. Orice

identificator al carui tip nu este dat se considera a fi de tip

int. Singurul tip de clasa de memorare care poate fi specificata

este register; daca aceasta e specificata, parametrul actual

corespunzator va fi copiat, daca este posibil, intr- un

registru in codul codului functiei. Un exemplu simplu de definitie

completa de functie este:

int max(a, b, c)

int a, b, c;

Aici int este specificator de tip;max(a, b, c) este declaratorul

de functie int a, b, c; este lista de declaratii pentru

parametrii formali; este blocul care da codul pentru

instructie.

'C'converteste parametrii actuali de tip float in double, astfel

ca parametrii formali declarati float isi vor avea declaratiile

ajustate pentru a se citi double. Astfel, daca o referinta la

un tablou in orice context (in particular cu un parametru

actual)este cnsiderata a avea sensul unui pointer la primul

element al unui tablou, declaratiileparametrilor formali de

genul 'tablou de' sint ajustate in 'pointeri catre'. In

final, intrucit structurile, uniunile si functiile nu pot fi

trecute unei functii, este fara utilizare declararea ca parametri

formali a unei structuri, uniuni sau functii (pointerii la astfel

de obiecte sint permisi).

10. 2. Definitii de date externe

O definitie de data externa are forma:

data definition:

declaration

Clasa de memorare a unei astfel de date poate fi extern (in

lipsa) sau static dar nu auto sau register.

11. Reguli despre domenii

Un program in C poate sa nu fie compilat tot deodata:

textul sursa al progarmului poate fi pastrat in mai multe fisiere

si rutine precompilate pot fi incaracte din biblioteci.

Comunicatiile intre functiile unui program pot fi apeluri

explicite sau utilitare de date externe.

Exista 2 feluri: primul, ce ar putea fi numit obiectivul

lexical al unui identificator, care este in esenta regiunea

unui program in timpul caruia el poate fi folosit fara a apare

eroarea de 'identificator nedefinit'; si al 2-lea obiectivul

asociat cu identificatori externi care se caracterizeaza prin

regula ca referinta la acelasi identificator extern sint referinte

la acelasi obiect.

11. 1 Domeniu lexical

Obiectivul lexical al identificatorilor declarati in

definitiile externe se intinde de la definitie pina la

sfirsitul fisierului sursa in care apare. Intinderea lexicala a

indentificatorilor care sint parametri formali persista in functia

cu care sint asociati. Scopul lexical al identificatorilor

declarati la inceput de bloc tine pina la sfirsitul

blocului. Intentia lexicala a etichetelor este in functia in care

apar.

Intrucit toate referintele la acelasi identificator extern se

refera la acelasi obiect(vezi 11. 2)compilatorul verifica

toate declaratiile aceluiasi identificator extern pt

compatibilitate; de fapt puterea lor se intinde asupra intregului

fisier pe care apar.

In toate cazurile, daca un identificator este explicit declarat

la inceputul unui bloc, incluzind blocul care constitue o

functie, orice declaratie al acelui identificator in afara

blocului este suspendata pina la sfirsitul bocului.

De reamintit (vezi 8. 5) ca identificatorii asociati cu

varaibile ordinare pe de o parte si acei asociati cu membrii

ai unor structuri sau reuniuni pe de alta parte, frmeaza doua

clase disjuncte fara conflict intre ele. Membrii (de reuniuni sau

structuri n. t. ) si etichetele urmeaza aceleasi reguli obiectuale

ca si identificatorii; numele declarate cu typedef sint de

aceasi clasa cu identificatorii ordinari. Ei pot fi redeclarati

in blocurile interne, dar un tip explicit se va da in declaratia

interioara.

typedef float distance;

De notat ca f trebuie declarata explicit in rutina apelanta pt

ca aparitia sa in g(f) nu este urmata de (.

14. 3. Tablouri, pointeri si indici

De fiecare data cind un identificator de tipul tablou apare intr-

o expresie el este convertit intr-un pointer catre primul

element al tabloului. Din cauza acestei conversii tablourile nu

sint lavlori. Prin definitie operatorul indice [] este

interpretat de asa maniera incit E1[E2] e identic cu *((E1)+(E2)).

Din cauza regulilor de conversie care se aplica lui +, daca E1

este tablou si E2 intreg atunci E1(E2) se refera la al E2-

lea membru al lui E1. Darin ciuda acestei aparente asimetrii,

indicii formeaza o operatie comutativa.

O regula soloida se aplica in cazul tablourilor

multidimensionale. Daca E este un tablou de ordinul 'n' si

indici ixjxxk atunci cind E apare intr-o expresie el va fi

convertit intr-un pointer la un tablou cu 'n-1' dimensiuni cu

indici jxxk. Daca se aplica operatorul *, explicit sau

implicit ca rezultat al utilizarii indicilor, rezultatul este un

tablou pointat de n-1 dimensiuni, care este imediat convertit

intr-un pointer. De exemplu:

int x[3][5];

Unde x este un tablou de intregi cu 3X5 elemente. Cind x apare

intr-o expresie, este convertit intr-un pointer catre(primul

din cele 3) tabloul de 5 membrii intregi. In expresia x[i],

care e echivalenta cu *(x+i), X este mai intii convertit intr-

un pointer asa cum s-a descris;i este apoi convertit in tipul

lui x, care implica inmultirea lui i cu lungimea

obiectului spre care pointeaza, adica 5 obiecte intregi.

Rezultatul se aduna si se aplica indirectarea producind

un tablou(de intregi) care este la rindul sau transformat

intr-un pointer la primul dintre intregi. Daca mai este un indice

acelasi procedeu se aplica din nou; acum rezultatul va fi un

intreg.

Rezulta ca in C tablourile sint stocate pe linii (ultimul

indice variaza cel mai repede ) si ca primul indice din

declaratie permite sa se de termine necesarul de memorie dar nu

are alt rol in calculul indicilor.

14. 4. Conversii de pointeri explicite

Unele conversii de pointeri sint permise doar au aspecte

dependente de implementare. Toate se specificaprin conversii

explicite de tip ca in &7. 2 si &8. 7.

Un pointer se poate converti in oricare tip de intreg suficient

de mare pentru a-l pastra. Dar a utiliza int sau long este

dependent de masina. Functiile de mapare sint dependente de, dar

nu vor surprinde pe aceea care cunosc structura de adresare a

masinii. Detalii se dau mai jos.

Un obiect de tip intreg poate fi convertit explicit in pointeri.

Maparea face ca un intreg convertit din pointer sa dea acelasi

pointer, depinzind de masina. Un pointer catre un tip poate

fi convertit intr-un pointer la alt tip. Pointerul rezultat

da exceptii de adresare la folosire daca pointerul subiect nu se

refera la un obiect aliniat corespunzator in memorie. Se

garanteaza ca un pointer la un obiect de o marime data poate fi

convertit intr-un pointer catre un obiect mai mic in dimensiune si

inapoi fara modificari.

De exemplu, rutina de alocare de memorie poate accepta o

marime (in biti, a unui obiect de alocat si sa returneze un

pointer char; acesta putind fi folosit conform scopului.

extern char *alloc();

double *dp;

dp=(double*)alloc(sizeof(double));

*dp=22. 0/7. 0;

alloc trebuie sa asigure (de o maniera dependenta de masina)

ca valoarea pe care o returneaza este corespunzatoare connversiei

intr-un pointer catre double < atunci utilizarea functiei este

portabila.

Reprezentarea pointerului la PDP-11 este un intreg de 16 biti si

se masoara in bytes; chars nu necesita aliniere speciala;

orice altceva trebuie sa aiba o adresa para.

Pe Honeywell un pointer are 36 de biti si e intreg; adresa de

cuvint e pe cei 18 biti din stinga, iar bitii care selecteaza

caracterul din cuvint in partea dreapta; deci pointerii char

sint masurati in unitati de 2 la 16 bytes; orice altceva in

unitati de 2 la 18 cuvinte; double si agregatele care le contin

trebuie sa fie la adresa de cuvint para.

IBM 370 si Interdata 8/32 sint similare. La ambele adresele

se masoara in bytes; obiectele elementare sint aliniate la

limite egale cu lungimea lor; pointeri catre short sint0 mod 2,

catre int sau float 0 mod 4 si la double 0 mod 8. Agregatele sint

aliniate la limitele stricte necesitate de constituenti.

15. Expresii 'constante'

In multe locuri C necesita expresii care dau o constanta: dupa

case, ca limite de tablouri, la initializari. In primele 2,

expresiile pot cuprinde doar constante intregi, constante

caracter, expresii tip sizeof conectate la operatorii binari:

+ - * / % & ^ << >> == != <> <= >=

Sau prin operatorii unari:

- ~

Sau prin operatorul ternar:

? :

Parantezele sint folosite pt grupare, nu pt apeluri de functii. O

latitudine mai mare o permit initializarile; in afara de

expresiile constante se poate aplica operatorul unar & la

obiecte externe sau statice, sau la tablouri externe sau

statice avind ca indici expresii constante.

Operatorul unar & poate fi aplicat implicit prin aaparitia de

tablouri fara indici sau functii. Regula de baza este ca

initializarile conduc la o constanta sau la o adresa a unui obiect

extern sau static plus sau minus o constanta.

16. Consideratii de portabilitate

Unele parti din C sint inerent dependente de masina. Lista care

urmeaza contine sursele de prorbleme cele mai importante:

Lungimea cuvintului de memorie si proprietatea aritmeticei in VF

sau impartirea intregilor au dovedit in practica ca nu sint

o problema. Alte fatete ale hardware-ului sint reflectate in

diversele implementari. Unele din ele, ca extensia de semn (

convertirea unui caracter negativ intr-un inttreg) si ordinea

bytelor in cuvint, sint neplaceri care trebuie observate atent.

Altele sint probleme minore.

Numarul de variabile register care pot fi plasate efectiv in

registre depind de la masina la masina, ca si seturi de

tipuri valide. Compilatoarele fac lucrurile corespunzator

propriei masini; declaratiile register excesive sau invalide

sint ignorate.

Unele dificultati cresc cind se folosesc practici de codificare

dubioase. Nu este recomandat a se scrie programe care depind de

aceasta proprietate.

Ordinea de evaluare a argumentelor functiilor nu este specifi

cata de limbaj. La PDP-11 este de la dreapta la stinga, la

altele de la stinga la dreapta. Ordinea de aparitie a efectelor

secundare nu e specificata.

Daca constantele caracter sint obiecte de tipul int,

constantele caracter multicaracter sin permise. Implementarea

specifica depinde de masina pt ca ordinea in care caracterele

sint plasate in cuvint variaza de la o masina la alta.

Cimpurile apar in cuvint si caracterele in intregi de la dreapta

la stinga in PDP si de la stinga la dreapta in alte masini. Aceste

diferente sint invizibile in programe izolate care nu fac

apel la dependente de tip (de exemplu conversia din pointer

int in pointer char si implementarea memoriei pointate) dar

trebuie considerate daca se doreste conformarea cu modalitatile de

memorare externa.

Limbajul acceptat de diversele compilatoare difera putin. Dar,

compilatorul pt PDP=11 folosit curent nu initializeaza structuri

de cimpuri de biti, nu accepta operatori de asignare in unele

contexte in care se foloseste valoarea asignarii.

17. Anacronisme

C este un limbaj in evolutie, unele constructii invechite pot fi

intilnite in programe mai vechi. Unele compilatoare suporta aceste

anacronisme, ele fiind pe cale de disparitie, raminind doar

problema portabilitatii.

Versiunile mai vechi de C permiteau forma =op in locul lui op=

pt asignare. Acestea duceau la ambiguitati, cum ar fi

x=-1

care acum inseamna scaderea unui 1 din x, = si - fiind

adiacente, dar care poate insemna si asignarea lui -1 lui x.

Sintaxa initializarilor s-a schimbat; la inceput semnul =

care anunta un initializator nu era prezent, adica in loc de

int x = 1;

se folosea

int x 1;

modificarea s-a facut pentru ca initializarea

int f(1+2)

semana cu o declaratie de functie atit de mult incit deranja

compilatoarele.

18. Sumar al sintaxei

Acest numar al sintaxei C-ului are scopul de a ajuta

intelegerea sa mai mult decit de a defini exact limbajul.

18. 1. Expresii

Expresii de baza sint:

expression:

primary

*expression

&expression

-expression

!expression

~expression

++lvalue

--lvalue

lvalue++

lvalue--

sizeof expression

(type-name)expression

expression binop expression

expression?expression:expression

lvalue asgnop expression

exprerssion, expression

primary:

identifier

constant

string

(expression)

primary(expression-listopt)

primary[expression]

lvalue. identifier

primary->identifier

lvalue:

identifier

primary[expression]

lvalue. identifier

primary->identifier

*expression

(lvalue)

Operatorii expresiilor primare

() []. ->

au cea mai mare prioritate si grupeaza stinga la dreapta.

Operatorii unari:

* & - ! ~ ++ -- sizeof(type-name)

au prioritatea sub cea a operatorilor primari dar mai mare decit a

operatorilor binari si grupeaza de la dreapta la stinga.

Operatorii binari si operatorul conditional grupeaza stinga la

dreapta si au priortatea descrescind asa cum e indicat

binop:

* / %

+ -

>> <<

< > <= >=

== !=

&

^

|

&&

?!

Operatorii de asignare au aceeasi prioritate

asgnop:

= += -= *= /=, %= >>= <<= &= ^= =

Operatorul, au cea mai mica prioritate, grupeaza stinga spre

dreapta

18. 2. Declaratii

declaration:

decl-specifiers init-declarator-listopt;

decl-specifiers:

type-specifier decl-specifiersopt

-specifier decl-specifiersopt

sc-specifier:

auto

static

extern

register

typedef

type-specifier:

char

short

int

long

unsigned

float

double

struct-or-union-specifier

typedef-name

init-declaration-list:

init-declarator

init-declarator, init-declarator-list

init-declarator:

declarator initializeropt

declarator:

identifier

(declarator)

*declarator

declarator()

declarator[constant-expressionopt]

struct-or-union-specifier:

struct

struct identifier

struct identifier

union

union identifier

union identifier

struct-decl-list:

struct-declaration

struct-declaration struct-decl-list

struct-declaration:

type-specifier struct-declarator-list;

struct-declarato-list:

struct-declarator

struct-declarator, struct-declarator-list

struct-declarator:

declarator

declarator:constant-expression

:constant-expression

initializer:

=expression

=

=

initializer-list:

expression

initializer-list, initializer-list

type-name:

type-specifier abstract-declarator

abstract-declarator:

empty

(abstract-declarator)

*abstract-declarator

abstract-declarator()

abstract-declarator[constant-expressionopt]

typedef-name:

identifier

18. 3. Enunturi

compound-statement:

declaration-list:

declaration

declaration declaration-list

statement-list

statement

statement statement-list

statement:

compound-statement

expression;

if(expression)statement

if(expression)statement else statement

while(expression)stament

do statement while(expression);

for(expression-1opt;expression-2opt;expression-3opt)statement

switch(expression)statement

case constant-expression:statement

default:statement

break;

continue;

return;

return expression;

goto identifier;

identifier:statement

;

18. 4. Definitii externe

program:

external-definition

external-definition program

external-definition:

function-definition

data-definition

function-definition

type-specifieropt function-declarator function-body

function-declarator

declarator(parameter-listopt)

parameter-list

identifier

identifier, parameter-list

function-body:

type-decl-list function-statement

function-statement

data-definition

externopt type-specifieropt init-declarator-listopt

staticopt type-specifieropt init-declarator-listopt

18. 5. Preprocesor

#define identifier token-string

#define identifier(identifier, , identifier)token-string

#undef identifier

#include 'filname'

#include <filname>

#if constant-expression

#ifdef identifier

#ifndef identifier

#else

#endif

#line constant identifier



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 1386
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved