1. NOTIUNI DE BAZA DESPRE LIMBAJUL C
Limbajul C a fost creat si implementat in 1972 de Dennis Ritchie la AT&T
Bell Laboratories pe PDP-11 legat de sistemul de operare UNIX. m7n15nf
In 1978 apare cartea lui Brian Kernighan si D. Ritchie, “The C Programming
Language”, reeditata in 1988. Neexistind un standard al limbajului, au
inceput sa apara discrepante intre diversele versiuni ale limbajului astfel
ca in 1983 ANSI infinteaza un comitet care in 1988 defineste standardul ANSI
pentru limbajul C.
Ca urmare a dezvoltarii P.O.O. din anii 1980, limbajul C a cunoscut dezvoltarea
C++, realizata de catre Bjarne Stroustrup tot de la AT&T, limbaj considerat
ca un superset al limbajului C.
Limbajul C a fost folosit la implementarea SO UNIX iar compilatorul limbajului
C a fost scris in mare masura chiar in limbajul C.
Limbajul C asigura o foarte buna portabilitate a codului, astfel incit codul
sursa poate fi folosit intr-un procent foarte mare indiferent de implementarea
utilizata si de diversele sisteme de calcul cu procesoare diferite.
Limbajul C este un limbaj de nivel mediu combinind avantajele limbajelor de
nivel inalt (PASCAL,FORTRAN, etc.) cu functionalitatea limbajelor de asamblare
(e numit limbaj de asamblare portabil).
Limbajul C permite:
-manipularea bitilor, octetilor, adreselor
-poseda conceptul de tipuri de date (char, int, float, double) permitind diverse
conversii de date
-are doar 32 de cuvinte cheie fiind usor de invatat
-permite compactarea programului sursa folosind expresii de atribuire, expresii
conditionale, operatii de incrementare, decrementare, etc.
-este un limbaj structurat permitind compartimentarea datelor si a codului.
Aceasta se realizeaza prin utilizarea functiilor care lucreaza cu variabile
locale evitindu-se efectele secundare din alte parti ale programului.
De asemenea in prima varianta a limbajului din 1972 nu se facea un test de compatibilitate
intre parametrii formali ai unei functii si argumentele efective folosite la
apelul functiei. Apareau astfel deseori diverse anomalii, standardul ANSI din
1988 introducind conceptul de prototip al unei functii pentru a evita erorile
inca din faza de compilare. Limbajul C ofera:
-mecanism macro puternic pentru a preveni duplicarea codului
-mai multe reprezentari pentru tipul intreg functie de caracteristicile hard
ale sistemului
-biblioteci de functii predefinite.
Limbajul C permite de asemenea:
-compartimentarea programelor in blocuri, blocuri cuprinse intre acolade, algoritmii
devenind asfel mai clari, mai eleganti, mai eficienti
-un control riguros al hardware-ului si al perifericelor asemanator limbajelor
de asamblare.
Daca initial limbajul C a fost folosit in vederea scrierii programelor de sistem
(SO, compilatoare, editoare, etc.) acum este folosit cu precadere la dezvoltarea
de aplicatii.
Limbajul C si C++ este cunoscut in ultima vreme ca un limbaj destinat dezvoltarii
de aplicatii si aceasta in special datorita eficientei si portabilitatii limbajului
(I se mai spune limbaj de banda larga).
2. STRUCTURA UNUI PROGRAM C
Limbajul C este un limbaj procedural la baza lui fiind procedura, numita functie.
Programele C au componente si trasaturi comune, facilitind dezvoltarea usoara
a unor noi aplicatii pornind de la o aplicatie existenta. Aceste programe contin
cel putin o functie fiecare din ele avind una sau mai multe instructiuni.
In limbajul C functiile sunt privite ca niste subrutine care pot fi apelate
din alte parti ale programului si care pot returna diferite valori.
Instructiunile in limbajul C sunt parti ale programului care executa anumite
operatii si care sunt continute in functii. Toate instructiunile in C se termina
cu ; .
Exemplu: printf(“Hello”);
Limbajul C nu recunoaste sfirsitul de linie LF ca si terminator, asfel ca
pe aceiasi linie pot exista mai multe instructiuni separate de ;.
Exemplu: printf(“Hello”);printf(“Yes”);
Structura unei functii in formatul cel mai simplu este:
nume_functie(parametri)
A declaratii; secventa_instructiuni;
S
unde:
-nume_functie este numele dat functiei C implementate
-parametri, reprezinta parametrii formali ai functiei
-declaratii, reprezinta declaratiile de variavile din cadrul functiei
-secventa_instructiuni, reprezinta 0 sau mai multe instructiuni C care pot fi
precedate de declaratii de variabile.
Limbajul C este un limbaj care face deosebirea intre literele mari si mici deci
este un limbaj context-senzitiv.
Exemplu:
Fact(); // si fact(); // pot fi doua functii total diferite
Intr-un program C trebuie sa existe o functie cu numele main care are anumiti
parametri impliciti dar care se foloseste in general fara parametri in felul
urmator, void main(void)
A declaratii; secventa_instructiuni;
S
Limbajul C poseda o biblioteca de functii C care pot fi utilizate in cadrul
programului. Informatii despre functiile din biblioteca sunt precizate in niste
fisiere de tip *.h, ( headere) standard care sunt adaugate programului printr-o
directiva preprocesor de tip, #include.
In cazul operatiilor de intrare/iesire, I/E, se specifica fisierul header standard
stdio.h cu ajutorul directivei:
#include “stdio.h”sau #include <stdio.h> constructie ce nu este o instructiune C care se introduce in cadrul functiilor,
nici un cuvint cheie al limbajului si nici nu se termina cu ;, dar se scrie
din prima coloana.
Unul din cele mai simple programe C care afiseaza un mesaj, Hello, C ar putea
arata astfel :
#include “stdio.h” //directiva cu informatii despre printf
void main(void) //inceputul functiei main
A //inceputul declaratiilor si instructiunilor printf(“Hello, C”); //apel functie de tiparire din biblioteca
S//main //acolada ce specifica sfirsitul functiei main si chiar
//a programului
Observatie: Comentariile in limbajul C se pot introduce astfel:
/* Comentarii */ iar in C++ se mai pot folosi si doua slash-uri , // astfel:
//Comentarii
Realizarea unui program C
In vederea realizarii unui program C de obicei se folosesc mediile de programare
de tip Borland, Microsoft, sau altele, care permit:
-crearea programelor sursa folosind un editor de texte integrat
-compilarea programului si obtinerea fisierului obiect
-editarea de legaturi care permite inglobarea si a altor module in vederea obtinerii
programului executabil
-depanatoare care permit verificarea unor programe executabile in vederea testarii
functionarii lor corecte.
Unele sisteme de operare , cum este UNIX, nu ofera inca astfel de medii de programare
dar poseda pentru fiecare etapa necesara realizarii unei aplicatii C programe
adecvate ca, editoare de texte, compilatoare, linkeditoare, depanatoare, etc.
3. TIPURI DE DATE DEFINITE IN C
Tipurile de date in C se specifica prin cuvinte cheie. In limbajul C aceste
cuvinte cheie cu care se specifica datele sunt prezentate in continuare:
Tip de date Reprezentare in biti Rang char 8 -27 I 27-1 unsigned char 8 0 I 28-1
asignedi char 8 -27 I 27-1 int 16 -215 I 215-1 dep. Calculator
asignedi int 16 -215 I 215-1 short ainti 16 -215 I 215-1 unsigned ainti 16 0 I 216-1 unsignedashort inti 16 0 I 216-1 signed ashort inti 16 -215 I 215-1 long ainti 32 -231 I 231-1
asignedi long ainti 32 -231 I 231-1 unsigned long ainti 32 0 I 232-1 float 32 ordin 10-38 la 1038 7 digiti double 64 ordin 10-308 la 10308 15 digiti precizie long double 80 ordin 10-4932 la 104932 19 digiti precizie
Tabel 1.1. Tipurile de date definite de standardul ANSI pentru limbajul C
sub DOS pe PC
3.1. Constante in C
Constanta este o valoare fixa utilizata in program avind un tip si o valoare
determinata de caracterele ce compun constanta. Valorile constantelor nu se
pot modifica in timpul executiei unui program. Cel mai frecvent constantele
sunt folosite pentru a initializa variabile la inceputul executiei programului.
Constantele in C se pot clasifica in:
-1)Constante intregi, care pot fi scrise in sisteme de numeratie in baza 8,
10, 16 si anume:
-Constante zecimale intregi, sunt formate dintr-un sir de cifre zecimale care
au prima cifra diferita de zero. Se reprezinta in calculator in conventia C2
pe 16 biti ca int si pe 32 biti ca long.
O constanta de tip long se termina cu l sau L.
O constanta zecimala intreaga are tipul unsigned, fara semn, daca se termina
cu u sau U.
Putem avea combinatii de (l, L) cu (u, U) in ori ce forma ca litere mari sau
mici.
Exemplu:
12345 constanta intreaga zecimala pe 16 biti
12345L constanta intreaga zecimala pe 32 biti
40000u constanta intreaga zecimala pe 16 biti fara semn
40000UL constanta intreaga zecimala pe 32 biti fara semn
-Constante octale intregi, reprezinta o succesiune de cifre octale (0 I 7) precedate
de un zero nesemnificativ.
Ele sunt de tip unsigned daca se reprezinta pe 16 biti, respectiv unsigned long
cind se termina cu l sau L si se reprezinta pe 32 de biti.
Exemplu:
0123 constanta intreaga octala pe 16 biti
0754L constanta intreaga octala pe 32 biti
-Constante hexazecimale intregi, sunt o succesiune de cifre hexazecimale precedate
de 0x sau 0X cu aceleasi proprietati ca si a celor octale.
Exemplu:
0xBCD constanta hexa intreaga pe 16 biti
0XAF6l constanta hexa intreaga pe 32 biti
-2)Constante flotante, reprezinta un numar rational si se compune din:
-o parte intreaga ca si o constanta zecimala
-o parte fractionara, caracterizata prin . si o succesiune de cifre zecimale
-un exponent ce incepe cu e sau E a+,-i sir de cifre zecimale ca factor ce exprima
o putere a lui zece, componente care pot fi vide dar nu toate odata.
Aceste constante se reprezinta in dubla precizie pe 64 de biti.
Pentru a le reprezenta in simpla precizie float, 32 biti, la sfirsit constanta
va fi urmata de f sau F.
Pentru a le reprezenta pe 80 de biti ca long double, constanta va fi urmata
de l sau L.
Exemplu:
123.3
.25
.1E-3
78fE1
12.45lE20
-3)constante de tip caracter, in cadrul calculatoarelor compatibile IBM PC se
foloseste codul ASCII la care caracterele se impart in:
-caractere negrafice cu valori cuprinse intre a0, 31i plus codul 127 (DEL).
-spatiu, codul 32
-caractere grafice cu valori cuprinse intre a33, 126i, ultimele doua categorii
reprezentind cracterele imprimabile
-caractere din setul extins cu valori cuprinse intre a128, 255i.
O constanta caracter are ca si valoare codul ASCII al caracterului pe care il
reprezinta. Tipul constantei de tip caracter este int pe 16 biti cu octetul
cel mai semnificativ pus pe valoare 0 in limbajul C la unele implementari, sau
0xFF (-1) in alte implementari.
Observatie: In limbajul C++ tipul constantei caracter este char pe 8 biti, in
mediul Borland se poate selecta in cadrul submeniului Code Generation, unsigned
char pentru a folosi setul extins de caractere ASCII.
Oconstanta caracter ce corespunde unui caracter imprimabil se reprezinta prin
caracterul respectiv inclus intre caractere apostrof:
‘a’ , valoarea 97 (0x61)
‘A’ , valoarea 65 (0x41)
‘0’ , valoarea 48 (0x30)
‘ ‘ , valoarea 32 (0x20)
O exceptie de la aceasta reprezentare o au:
-caracterul backslash, \, care se reprezinta ‘\\’, adica prin 2
backslashuri intre apostroafe
-caracterul apostrof, ‘, care se reprezinta ‘\’’, adica
prin backslash si apostrof intre apostroafe
-caracterul ghilimele, “,care se reprezinta ‘\”’, adica
prin backslash si ghilimele intre apostroafe.
Costanta caracter backslash, \, se poate utiliza pentru a defini constante caracter
si pentru caractere negrafice. Se spune ca backslash introduce o secventa escape
(de evitare).
Exemplu:
Constanta caracter Cod ASCII Denumire Utilizare
‘\a’ 7 BELL activare sunet
‘\b’ 8 BS backspace
‘\t’ 9 HT tab. Orizontal
‘\n’ 10 LF Linefeed, rind nou
‘\v’ 11 VT tab. Vertical
‘\f’ 12 FF Form Feed, salt de pagina imprimanta
‘\r’ 13 CR Carriage Return, poz. Curs. Col. 1 rind curent
‘\”’ 34 ghilimele
‘\’’ 39 apostrof
‘\\’ 92 backslash
Secventa escape se poate folosi pentru a defini constante caracter pentru
orice caracter al codului ASCII cu urmatoarele constructii:
-a)‘\ddd’, unde ddd reprezinta cifre octale si constructia reprezinta
constanta caracter corespunzatoare codului ASCII egal cu valoarea intregului
octal ddd.
Exemplu:
‘\a’ = ‘\7’ este BELL
‘\b’ = ‘\10’ este BS
‘\”’ = ‘\42’ sunt ghilimele
Constantele caracter din intervalul a128, 255i se definesc prin secvente escape
care indica codul acestora cum ar fi ‘\377’, care corespunde codului
ASCII 255 cu reprezentare pe 8 biti (char) sau 16 biti (int).
-b)’\xdd’, unde dd reprezinta cifre hexa si constructia reprezinta
constanta caracter corespunzatoare codului ASCII egal cu valoarea intregului
hexa dd.
Exemplu:
‘A’ = ‘\101’ = ‘\x41’ corespunzind valorii
65
-4)constante de tip sir de caractere, reprezinta o succesiune de zero sau mai
multe caractere incluse intre ghilimele si care nu fac parte din sir (tipul
lor este unsigned char).
La scrierea caracterelor din compunerea sirului se pot folosi si secvente escape.
Un sir se continua pe rindul urmator folosind caracterul \ (backslash), care
se tasteaza la sfirsitul rindului care se continua dupa care se trece pe rindul
urmator cu ENTER si se continua scrierea caracterelor sirului.
Caracterele unui sir sunt pastrate contiguu in memoria calculatorului prin codurile
ASCII, dupa ultimul caracter pastrindu-se caracterul NULL de valoare 0 (zero)
ca si marcaj de sfirsit de sir. Deci in C un sir ocupa 1 octet mai mult decit
numarul de caractere din sir.
De remarcat ca:
‘A’ constanta caracter A se pastreaza intr-un octet (conv. C++)
in care va fi valoarea 65 = 0x41
“A” constanta sir (de caractere) A se pastreaza in 2 octeti, primul
cu valoarea 65 si al doilea cu valoarea 0.
Exemplu:
-“a\1b” este o constanta sir ce are in compunere caracterele: a de cod 97
SOH, \1, de cod 1 b de cod 98
NULL de cod 0, deci 4 octeti cu valorile: 97| 1|98| 0|
-“a\13” este o constanta sir ce are in compunere caracterele: a de cod 97
VT, \13, de cod 11
NULL de cod 0, deci 3 octei cu valorile: 97|11| 0|
-“a\1\63” este o constanta sir ce are in compunere caracterele: a de cod 97
SOH, \1, de cod 1
3, \63, de cod 51
NULL de cod 0, deci 4 octei cu valorile: 97| 1|51| 0|
-“\1751” este o constanta sir ce are in compunere caracterele
S, \175, de cod 125
1 de cod 49
NULL de cod 0, deci 3 octeti cu valorile: 125|49| 0|, constanta care insa se
poate scrie mai simplu “S1”.
Observatie: Caracterul NULL, ‘\0’, nu poate fi folosit decit la
sfirsitul unui sir de caractere.
-5)caractere spatii albe (White spaces)
Prin spatiu alb se intelege unul din caracterele:
-spatiu, ‘ ‘
-tabulator orizontal, HT, ‘\t’ caracter rind nou, LF, ‘\n’.
Setul caracterelor spatii albe difera la diverse implementari ale limbajului
C.
De remarcat ca in C un comentariu poate aparea inserat oriunde este legal sa
apara un spatiu alb.
3.2. Variabile simple in C
Intr-un program pe linga date constante se folosesc si date variabile care
isi schimba valoarea in timpul executiei programelor.
Referirea la o data variabila se face prin numele asociat care ne permite:
-accesul la valoarea ei
-schimbarea valorii daca este necesar.
O data izolata nu are legatura cu alte date, numele unei date izolate reprezinta
o variabila simpla.
Unei date izolate ii corespunde un tip. In timpul executiei programelor
se poate schimba valorile unei date variabile dar nu si tipul ei.
Tipurile de date variabile in C se specifica prin cuvinte cheie. In limbajul
C aceste cuvinte cheie cu care se specifica datele sunt: char int short long signed unsigned float double void.
Tipurile de variabile sunt recunoscute prin cuvintele cheie: char, pentru caractere int, pentru intregi cu semn void, neprecizat float, real simpla precizie double, real dubla precizie, iar modul de implementare poate fi modificat cu
ajutorul declaratiilor suplimentare signed, unsigned, long, short, (vezi tabelul
1.1).
Corespondenta intre numele unei date variabile si tipul ei se defineste printr-o
declaratie.
O variabila se declara prin: tip nume_variabila; sau tip lista_de_nume; unde tip este un cuvint cheie din tabelul 1.1. si unde nume_variabila
este numele variabilei in locul ei putind fi lista_de_nume ca si o lista de
variabile.
Exemplu: int produs; int produs, suma, medie;
In limbajul C declararea unei variabile (liste de variabile) trebuie sa se termine
cu ;.
Variabilele reprezinta spatii in memoria calculatorului avind acelasi rol in
timp dar care pot contine valori diferite la momente diferite de timp.
Mai general printr-o variabila se intelege o locatie de memorie care poate pastra
un obiect ales dintr-o multime, (clasa) prestabilita de obiecte.
Exemplu: int n, m, i, j=2; //int reprezinta multimea (clasa, domeniul)
// n, m, i, j, locatii in memorie unde se pastreaza
Multimea este domeniul de definitie al variabilei, iar locatia este zona de
memorie capabila sa memoreze ori ce valoare din domeniul de definitie.
Exemplu: int i; int este multimea intregilor adresa lui i este locatia unde se pot memora ori ce date de tip intreg care
vor fi referite cu numele i.
Deci la nivelul implementarii unei variabile ei ii corespunde o zona de
memorie din memoria interna a calculatorului careia ii corespund doua
valori:
-adresa zonei de memorie (referinta) asa numita l-value, left-value, adica expresie
utilizabila in partea stinga a unei expresii de atribuire
-valoarea memorata in acea zona, asa numita r-value, right value.
Despre l-value si r-value pot fi facute mai multe precizari dupa introducerea
mai multor notiuni specifice limbajului C.
3.3. Tablourile in C
Tablourile reprezinta un grup de date de acelasi tip care formeaza o multime
ordonata de elemente la care ne putem referi folosind indici.
Unui tablou i se da un nume.
Tipul comun al elementelor unui tablou reprezinta tipul tabloului respectiv.
Un tablou cu n dimensiuni, foloseste n indici si reprezinta un tablou n-dimensional.
Observatie:
Daca n = 1 avem notiunea de vector, char taba100i;
Daca n = 2 avem notiunea de matrice, double dmata10ia5i; //matrice de 10 linii
si 5 coloane
Referirea la elementele unui tablou se face cu o variabila cu indici. O variabila
cu indici se compune din numele tabloului si valorile indicilor, fiecare indice
fiind o expresie inclusa intre paranteze patrate. Valoarea inferioara a indicilor
este 0 in limbajul C.
Un tablou in C se declara prin: tip numealim1ialim2i…alimni unde:
-tip, este un cuvint cheie din cele predefinite
-limi, este limita superioara a indicelui i, indice care are valori cuprinse
intre 0 si limi-1. Aceste limite sunt expresii constante adica pot fi evaluate
la compilare.
-nume, este numele tabloului. Numele unui tablou in C este un simbol care are
ca si valoare adresa primului element din tablou (tab are ca si valoare adresa
elementului taba0i, iar dmat are ca si valoare adresa elementului dmata0ia0i).
3. Structuri in limbajul C
O structura reprezinta o multime ordonata de elemente grupate in vederea utilizarii
lor in comun.
Exista mai multe formate de descriere a structurilor, cel mai folosit fiind: struct anume_structi
A lista_declaratii;
Sanume1,nume2,…,numeni unde:
-nume_struct, este un nou tip de date, tip definit de catre utilizator
-lista_declaratii, este o lista prin care se declara componentele unei structuri.
-nume1,…,numen sunt date de tip nume_struct, putind lipsi la definirea
structurii caz in care este obligatoriu sa fie precizat nume_struct.
Exemplu: struct data_calend
A int zi; char lunaa11i; int an;
S; ,constructie prin care s-a definit un nou tip de date, data_calend, data de
tip utilizator. struct complex
A double real; double imag;
Sa,b; , structura de tip complex, a si b fiind date de tip complex.
Referirea la elementele unei structuri, de exemplu la partea reala si cea imaginara
a datei a se poate face prin:
-utilizarea operatorului . (punct) prin care a.real respectiv a.imag reprezinta
partea reala respectiv imaginara a datei a
-de asemenea in C se pot defini pointeri spre structuri pentru a transfera structurile.
In locul numelui structurii sa zicem complex se cunoaste un pointer spre structura,
p. In acest caz am putea avea: complex *p; //p este pointer spre o structura de tip complex p=&a; //p va avea ca si valoare adresa datei a care este si ea o structura
de tip complex
Accesul la partea reala respectiv imaginara a datei a se poate face prin:
(*p).real respectiv prin
(*p).imag sau folosind operatorul sageata mai compact prin: p->real respectiv p->imag.
Daca prin tip intelegem o multime de date impreuna cu operatiile care pot fi
efectuate cu aceste date, atunci prin tip utilizator, cum este struct, se defineste
multimea si reprezentarea datelor tipului utilizator respectiv.
De asemenea utilizatorul mai defineste operatiile cu aceste date prin intermediul
unor functii.
In cazul tipurilor predefinite cunoastem:
-multimea si reprezentarea datelor
-operatiile cu aceste date.
Exemplu:
Multimea numerelor intregi pe calculatoare compatibile IBM PC cu procesoare
Intel 386 in cadrul mediului TC 2.0 contine valori cuprinse intre -215 si 215-1,
datele fiind reprezentate in conventia C2 pentru numere intregi pe 16 biti.
Operatiile predefinite cu aceste numere sunt: +, -, *, /.
Observatie:
In cadrul tipurilor utilizator nu se precizeaza legatura intre modul de reprezentare
al tipului si functiile care definesc operatiile.
De aceea in C++ s-a introdus notiunea de clasa, caz in care se definesc tipurile
abstracte de date, in cadrul claselor putind fi precizate legaturile dintre
date si functiile (metodele) care definesc operatii asupra lor.
De cele mai multe ori datele sunt protejate si metodele sunt publice. Accesul
la date in acest caz putind fi facut doar prin intermediul metodelor definite
in acest scop, din cauza faptului ca datele sunt protejate.
(La structuri de date si clase se va reveni)
3.5. Apelul si prototipul functiilor
O functie in C se defineste prin antetul si corpul ei.
Antetul are urmatorul format (forma simpla): tip nume(lista_param_formali) unde:
-tip, este tipul rezultatului returnat de catre functie. Daca tipul nu este
specificat functia returneaza un intreg. Daca functia nu returneaza nimic se
va specifica tipul void care previne utilizarea ei in partea dreapta a unei
operatii de asignare
-lista_param_formali, poate fi vida sau pot exista mai multe declaratii de parametrii
separate prin virgule. Acesti parametri se aloca pe stiva.
Exemplu: void adcomplex(complex a, complex b)
Corpul unei functii contine o succesiune de instructiuni precedate eventual
de o succesiune de declaratii de tip variabile locale.
Exemplu:
A real=a.real+b.real; imag=a.imag+b.imag;
S unde real si imag sunt doua variabile de tip double globale.
O functie se apeleaza cu o constructie de forma: nume(lista_param_efectivi); unde:
-nume este numele functiei
-lista_param_efectivi este o lista vida sau formata din mai multi parametri
separati prin virgula, care se mai numesc argumente.
Un parametru efectiv este o expresie si corespunde prin ordine si tip cu cei
formali.
Un parametru efectiv poate fi si un tablou, caz in care se transmite adresa
tabloului si apelul se zice ca este prin referinta, in rest apelul se considera
prin valoare cu exceptia cazurilor cind se folosesc variabile de tip pointer
sau referinte.
Exemplu:
Fie tab un tablou de intregi de 100 de elemente, declarate prin: int taba100i;
Daca vrem sa apelam o functie f care sa aiba ca si parametru acest tablou, atunci
apelul va fi: f(tab);
In acest caz antetul functiei ar putea fi: void f(int xa100i) sau void f(int xai).
De multe ori se pune problema de a apela in cadrul unei functii alte functii
care urmeaza sa fie definite ulterior. Pentru a putea fi posibil functia care
urmeaza a fi definita ulterior trebuie sa aiba un prototip care sa preceada
definirea si utilizarea ei.
Prototipul prezinta informatii referitoare la:
-tipul valorii returnate de functie
-existenta si tipurile parametrilor functiei.
Un prototip poate fi scris ca:
-antetul functiei respective urmata de ;
-antetul functiei respective la care se omit numele parametrilor formali si
se precizeaza doar tipul lor, urmata de ;
-antetul la care se omit atit numele cit si tipul parametrilor formali, urmata
de ; (nu la toate compilatoarele)
Exemplu: void func(int x, long yai, double z); sau void func(int, long ai, double);
Observatie:
Daca un parametru efectiv are un tip diferit de cel corespunzator din antet
sau prototip, compilatorul C converteste automat valoarea parametrului efectiv
spre tipul indicat in antet sau prototip.
In bibliotecile standard ale limbajului C si C++ exista functii predefinite
care pot fi usor folosite de catre utilizatori. Apelul lor implica existenta
prototipului lor.
Pentru aceste functii standard exista anumite fisiere standard, headere, de
tip *.h, (stdio.h, string.h, etc.) care contin prototipul unor functii inrudite.
Aceste fisiere headere se includ printr-o directiva preprocesor.
3.6. Preprocesarea in C
Preprocesarea permite prelucrarea unui program sursa C sau C++ inainte de
a fi supus compilarii.
Ea asigura:
-includeri de fisiere cu text sursa
-definitii si apeluri de macro-uri
-compilare conditionata.
Preprocesarea este specificata prin prezenta ca prim caracter a caracterului
#.
Includerea de fisiere cu text sursa se face cu constructiile:
#include “specif_de_fisiere” sau
#include <specif_de_fisiere> unde specif_de_fisiere depinde de sistemul de operare dar in general contine:
-un nume de fisier urmata de extensia lui
-calea daca este necesara pentru localizarea fisierului.
Daca specificatorul de fisiere este inclus intre < >, atunci se includ
fisiere standard si cautarea are loc conform specificatiilor prezentate in mediul
de programare (la mediul TC2.0, submeniul Directories din meniul Options).
Daca se folosesc “ “, fisierul va fi cautat in directorul curent
sau conform caii precizate in mediul de programare.
Exemplu:
#include <stdio.h> // prototip pentru functii de I/E
#include “fis1.cpp” //include textul sursa fis1.cpp incepind cu
cautarea din directorul curent
#include “c:\\users\\an_x\\prog\\fis2.cpp” // se precizeaza calea
folosind 2 backslashuri
Un text inserat cu #include poate contine constructii #include pentru alte
fisiere.
Constructiile de tip #include sunt valabile din locul in care sunt introduse
si de aceea de obicei ele se introduc la inceputul unui fisier pentru a fi valabile
in tot fisierul sursa care se va compila.
Directivele de preprocesare pot fi utilizate si la substituiri de succesiuni
de caractere. In acest caz se utilizeaza directiva #define astfel:
#define nume succes_de_caractere, costructie care este deseori folosita pentru
a defini constante numite constante simbolice.
Exemplu:
#define A 100 // A se substituie cu 100
#define B A+120 // B se substituie cu 100+120
#define C (A+120) // C se substituie cu (100+120) iar daca in program folosim constructii de forma:
X=3*B; //X va fi 3*100+120 sau
X=3*C; //X va fi 3*(100+120)
Constructia
#define nume succes_de_caractere autorizeaza substitutia pe care o defineste pina la:
-sfirsitul fisierului in care este scrisa sau
-pina la o constructie de forma
#undef nume, costructie care o anuleaza.
Exemplu:
#define A 100
…. float z; int xaA+1i; //xa100+1i
#undef A
#define A 3.5 z=2*A; //2*3.5
…
Directiva #define se foloseste cel mai des la definirea de constante simbolice
cum ar fi: #define PI 3.14159
FUNCTIA printf SI FORMATELE SALE DE SCRIERE
Functia printf permite formatarea si afisarea de caractere si valori catre
iesirea standard, stdout.
Ea se apeleaza printr-o constructie de forma: printf(formata,argii); unde:
-format, reprezinta un sir de caractere care defineste textele, secventele escape
si formatele datelor care se scriu in caz ca exista argi, adica formate de scriere
precizate prin specificatori de format
-argi, sunt argumente care trebuie sa corespunda specificatorilor de format,
argi corespunzind specificatorului i.
Datele gestionate de catre printf sunt supuse unor transformari din cauza existentei
unui format intern si a altuia extern a datelor. Specificatorii de format definesc
aceste conversii.
Observatie: Daca sunt mai multe argumente decit specificatori de format, acestea
sunt ignorate, iar daca nu sunt suficiente argumente pentru toti specificatorii
de format, rezultatele pot fi nedefinite.
Specificatorii de format incep totdeauna cu caracterul %. Formatele specifice
utilizate in printf sunt:
%c -afisare caracter unic. Valoarea lui este interpretata ca fiind codul ASCII
al caracterului
%s -afisare sir de caractere pina la caracterul NULL
%d -afisare numar intreg in baza zece cu semn
%i -afisare numar intreg in baza zece cu semn
%u -afisare numar intreg in baza zece fara semn realizind conversia unei date
binare de tip unsigned in zecimal
%f -afisare numar real, notatia zecimala realizind conversia datei de tip float
sau double la forma, intreg.fractionar
%e(E) -afisare numar real, notatia exponentiala realizind conversia datei de
tip float sau double la forma, intreg.fractionarEa+,-iexp
%g(G) -afisare numar real, cea mai scurta reprezentare dintre %f si %e
%x -afisare numar hexazecimal intreg fara semn convertind datele int sau unsigned
%o -afisare numar octal intreg fara semn convertind datele int sau unsigned
%p -afisarea unui pointer la void (ori ce tip de data) sub forma unei adrese
compuse din segment si offset in afisare cu cifre hexa
%n -afisarea unui pointer la int sub forma unei adrese compuse din segment si
offset in afisare cu cifre hexa, valoarea fiind memorata in intregul a carui
adresa este data ca si argument
In plus mai pot fi utilizate urmatoarele prefixe: l -cu d, i, u, x, o, pentru date de tip long
-cu f, e, g, pentru date de tip double
L -cu f, e, g, pentru date de tip double h -cu d, i, u, x, o, pentru date de tip short.
De asemenea unele compilatoare accepta si prefixele (F, N), (far, near) pentru
conventii de adresare in memorie.
Pentru a specifica:
-dimensiunea cimpului de afisare
-precizia de afisare a datelor, in cadrul datelor, specificatorul de format
va arata astfel:
%a-,+ia.b f unde:
% -semnul inceputului specificatorului de format
- -alinierea are loc la stinga
+ -alinierea are loc la dreapta a -dimensiunea minima a cimpului (inclusiv punctul care se scrie daca este cazul) b -precizia de afisare f -formatul tipului de data specific, f pentru real, d pentru intreg, s pentru
sir
Observatii:Daca: a -este > decit numarul de caractere de scriere a valorii reale date, atunci
scrierea se va face pe numarul de coloane dat de a cu completarea de caractere
nesemnificative (spatii) la stinga sau la dreapta a -este < decit numarul de caractere de scriere a valorii reale date, atunci
valoarea lui se ignora, scrierea se face fara aliniere pe un numar de coloane
egal cu numarul de caractere al valorii reale, adica cite zecimale este necesar
. -punctul este optional, dar daca este prezent dupa el se defineste precizia
datei, b si anume:
-daca data este flotanta, precizia da numarul de zecimale care se scriu
-daca data este intreaga, precizia da numarul minim de digiti de afisare a numarului.
Daca nu are atitia digiti se adauga zerouri
-daca data este sir de caractere, precizia da numarul total de caractere care
se scriu
-dupa caracterul % apare un alt caracter diferit de cele prezentate, caracterul
% (primul daca sunt mai multe) se ignora si se afiseaza caracterul imediat ce
urmeaza dupa el.
Functia printf returneaza un intreg cu urmatoarea semnificatie:
-numarul de octeti (caractere) care se afiseaza la terminal daca nu este eroare
-valoarea -1 in caz de eroare.
Prototipul ei este in biblioteca stdio.h.
Exemplu: void main(void)
A int ev, num; char poz; float timp,val; ev=5; poz=’M’; timp=12.30; num=12345; val=10.12304; printf(“\nEvenimentul %c are numarul %d”,poz,ev); printf(“si a avut loc la %f \n”,timp);// va afisa pe ecran cu aliniere
la 6 digiti pentru float
//Evenimentul M are numarul 5 si a avut loc la 12.300000 printf(“timp = %5.2f\n”,timp);
//timp = 12.30 printf(“val nefor=%f val form=%5.2f\n”,val,val);
//val nefor=10.123040 val form=10.12 printf(“%-10f \n%10f \n”,val,val);
//10.123040
// 10.123040 printf(“%d\n”,num);
//12345 printf(“numar= %+10d\n”,num);
//numar= 0000012345 printf(“3.8d\n”,1000);
//00001000 printf(“10.15s\n”, “Acesta este un text”);
//Acesta este un
S//main
5. FUNCTIA scanf
Aceasta functie permite introducerea de date tastate la terminalul standard
stdin, date specificate de argumentele argi sub controlul unor formate.
Apelul functiei este sub forma: scanf(format a,argii); unde:
-format, reprezinta un sir de caractere care defineste formatele datelor si
eventual textele aflate la stdin. Caracterele albe sunt neglijate. In rest sunt
specificatori de format si alte caractere care trebuie sa existe la intrare
in pozitiile corespunzatoare, caractere in general folosite la efectuarea de
controale asupra datelor citite.
-argi, sunt argumente care corespund adreselor zonelor in care se pastreaza
datele citite dupa ce au fost convertite din formatul lor extern in cel intern
corespunzator. (Ele sunt precedate de operatorul de adresare & care nu este
obligatoriu in cadrul tablourilor).
Specificatorii de format au rolul de:
-a controla introducerea datelor
-a defini conversiile din formatele externe in cele interne.
Specificatorii de format sunt similari cu cei de la printf, doar ca scanf nu
accepta formatele %i si %g.
Intre % si literele specifice specificatorului de format se mai pot utiliza:
-un caracter * optional, precizind faptul ca, cimpul de la intrare care urmeaza
a fi preluat si interpretat este functie de tipul specificat, dar nu este memorat
-un sir de cifre optional care defineste lungimea maxima a cimpului din care
se citeste data sub controlul formatului respectiv. scanf citeste toate cimpurile care corespund specificatorului de format inclusiv
eventuale texte prezente in cimpul format. In caz de eroare, citirea se opreste,
functia scanf returnind numarul de cimpuri citite corect.
Prototipul functiei scanf este in stdio.h.
Observatie:
Daca nume:
-este numele unei variabile simple atunci, &nume, reprezinta adresa de inceput
a zonei de memorie alocata variabilei nume
-este numele unui tablou in C, atunci nu mai este obligatoriu utilizarea operatorului
de adresare &, nume avind ca si valoare chiar adresa de inceput a zonei
de memorie alocata tabloului respectiv.
Exemplu: void main(void)
A int ev; char poz; float timp; printf(“\nIntroduceti pozitia, evenimentul, timpul \n”); scanf(“%c%d%f”,&poz,&int,&timp); printf(“\nEvenimentul %c are numarul %d”,poz,ev); printf(“ si a avut loc la %5.2f \n”,timp);
S//main
Observatie:
La specificatorul %s, pentru siruri de caractere, dupa ultimul caracter citit
se pastreaza in mod automat caracterul NULL, adica ‘\0’.
Citirea cu scanf a sirurilor de caractere incepe cu primul caracter care nu
este caracter alb si se termina la caracterul dupa care urmeaza un caracter
alb, sau cind se ajunge la lungimea maxima de caractere indicata in specificatorul
de format.
Specificatorul %1s, permite citirea unui singur caracter dar el se deosebeste
de %c prin:
-%1s, citeste primul caracter diferit de caracterul alb, iar %c nu tine cont
de aceasta
-%1s implica memorarea caracterului NULL dupa caracterul citit, lucru ce nu
are loc la %c
Exemplu: char car; char cara2i; scanf(“%c”,&car); = scanf(“%1s”,car);
6. STRUCTURI DE CONTROL SI INSTRUCTIUNI IN LIMBAJUL C
Limbajul C fiind un limbaj structurat admite urmatoarele structuri de control:
-secventiala
-conditionala (alternativa, decizionala)
-recursia (repetitia coditionata anterior).
Un program realizat cu aceste structuri este un program structurat. Ulterior
s-au mai introdus inca doua structuri si anume:
-structura selectiva
-strucrura repetitiva conditionata posterior, permitidu-se astfel o mai mare
flexibilitate in programare. Aceste structuri sunt realizate in C astfel:
-secventiala, cu instructiunea compusa
-conditionala, cu instructiunea if
-selectiva, cu constructia switch…case
-repetitiva conditionata anterior cu while si for
-repetitiva conditionata posterior cu do…while.
Instructiunile expresie si vida permit realizarea structurilor de control precizate.
Instructiunile return, break, continue si goto permit o mai mare flexibilitate
in programare.
Instructiunea vida, se reduce la caracterul ; si nu are nici un efect.
Instructiunea expresie are formatul: expresie; si poate fi o instructiune de atribuire, de apel de functie, etc.
Exemplu: int i,j; float q,r; i=5; j=i+10; q=r=i/j+9.5; i++; puts(“Apasa o tasta pentru continuare”): getch();
Declaratiile in C permit utilizatorului sa-si declare date de diferite tipuri
(predefinite sau utilizator) care pot fi si initializate.
Instructiunile au rolul de a prelucra datele.
6.1. Structura secventiala
Aceasta structura este realizata cu ajutorul instructiuni compuse si are urmatoarea
forma:
A lista_de_declaratii; lista_instructiuni;
S
Daca exista declaratii ele precizeaza variabile care sunt definite atit timp
cit controlul programului este la o instructiune din compunerea listei de instructiuni.
6.2. Structura conditionala (alternativa, decizionala)
Aceasta structura poate avea formatele: if (expresie) instructiune sau if (expresie) instr1 else instr2
Daca expresie este diferita de zero, adica adevarata, atunci se executa instructiune
respectiv instr1, altfel se executa prima instructiune dupa if si respectiv
instr2 si apoi prima instructiune dupa if.
Exemplu: char ch; ch=getche(); if (ch==’y’) printf(“Ati tastat y\n”); else printf(“Nu ati tastat y\n”);
Instructiunile pot fi instructiuni compuse sau chiar instructiunea if. Caz in
care avem imbricari. In acest caz se are in vedere regula de asociere a alternativelor
else cu alternative if astfel incit un else este asociat cu cel mai apropiat
if care nu are propriul lui else asociat.
6.3. Structura selectiva
Structura se realizeaza cu ajutorul constructiei switch … case, cu urmatorul
format: switch (expresie)
A case c1: sir_1;
abreak;i case c2: sir_2;
abreak;i
… case cn: sir_n;
abreak;i
adefault: siri
S unde: c1, …, cn sunt constante ce pot fi:
-intregi
-caracter
-expresii constante. sir_1, …, sir_n, sir, sunt succesiuni de instructiuni.
Executia se face astfel:
-se evalueaza expresie
-se compara expresie cu c1, …, cn, pe rind. Daca valoarea:
-expresie = ci atunci se executa sir_i si daca:
-dupa aceea urmeaza break, se trece la instructiunea imediat urmatoare dupa
switch.
-daca nu este break la sfirsitul unei alternative, dupa executia sir_i se trece
automat la sir_i+1, si tot asa mai departe daca nu este break
-expresie ? ci se ajunge la default, executindu-se instructiunile specificate
prin sir, dupa care se iese in afara structurii.
Exemplu: switch (expresie) if (expresie == c1)
A A case c1: sir_1; sir_1; case c2: sir_2; sir_2;
S S
= else if(expresie == c2)
A sir_2;
S
Pe cind structura switch … case cu break prezentata anterior este echivalenta
cu: if (expresie == c1) sir_1; else if (expresie == c2) sir_2; else if (expresie == c3) sir_3; else if
… else if (expresie == cn) sir_n; else sir;
Exemplu: char ch; printf(“Introdu o litera”); ch=getche(); switch(ch)
A case ‘a’: case ‘e’: case ‘i’: case ‘o’: case ‘u’: printf(“\nEste o vocala”);break; default: printf(“\nEste o consoana”);
S
6. Structura repetitiva conditionata anterior
Aceasta se realizeaza cu ajutorul instructiunilor:
-a)Instructiunea while cu urmatorul format:
while (expresie) //antet
A instructiuni; //corpul
S unde daca:
-expresie ? 0 (adevarat) atunci se executa instructiuni, dupa care se revine
la punctul in care se evalueaza din nou expresia, corpul executindu-se atit
timp cit expresia este adevarata adica, expresie ? 0. Cind expresie = 0 se trece
la urmatoarea instructiune dupa ciclul while.
- expresie = 0 de la inceput, atunci corpul nu se executa nici o data.
Observatie:
Instructiuni poate fi si o instructiune compusa.
Putem avea si while in while si printr-o functie standard exit() sa fortam iesirea
fara a evalua expresia lucru ce poate fi realizat si in cadrul instructiunii
if.
Exemplu: float taba10i,tmp; int l=0,j=9;
// inverseaza elementele din tab…
while(l<j)
A tmp=tabali; tabali=tabaji; tabaji=tmp; l++; j--;
S
-b)Instructiunea for are urmatorul format: for(exp1;exp2;exp3)
A instructiuni;
S unde:
-exp1, exp2, exp3 sunt expresii cu urmatoarea semnificatie:
-exp1, reprezinta partea de initializare a ciclului for
-exp3, reprezinta partea de reinitializare a ciclului for
-exp2, reprezinta conditia de continuarea ciclului for si are acelas rol cu
expresia expresie din ciclul while.
Ciclul for se executa astfel:
-se executa secventa de initializare data de exp1
-se evalueaza exp2. Daca rezultatul este:
-True, exp2 ? 0, se executa corpul
-False, exp2 = 0, se trece la instructiunea urmatoare ciclului
-dupa executia corpului se executa exp3, reinitializarea.
Observatii:
-Daca exp2 = 0, de la inceput, atunci corpul nu se executa niciodata.
-expresiile din antet pot fi si vide caz in care avem: for(;;) instructiuni; = while(1) instructiuni; caz in care avem cicluri infinite din care se iese cu ctrl-C in cadrul SO DOS.
Exemplu:
#define N 10 int l; double fact;
…. for(l=N,fact=1;l;l--) fact*=l; //calculeaza factorialul
Observatii:
In general ciclurile for si while pot fi ori cind inlocuite unul cu altul si
anume: for(exp1;exp2;exp3) exp1;
A while(exp2) instructiuni; A
S ? instructiuni; exp3;
S sau
while (expresie) for(;expresie;)
A A instructiuni; ? instructiuni;
S S
6.5. Structura repetitiva conditionata posterior
Aceasta structura se realizeaza cu constructia do…while cu urmatorul
format: do
A instructiuni;
S
while(expresie) care se executa astfel:
-se executa instructiuni
-se evalueaza expresie. Daca:
-expresie este adevarata adica expresie ? 0 atunci se revine la executia instructiuni
-expresie este falsa, adica expresie = 0 atunci se iese din ciclu
Exemplu: int num=0, total=0;
… do //tipareste numerele naturale de la 0 la 9 si numarul lor progresiv
A total+=num; printf(“num= %d total = %d”,num,total); num++;
S
while(num < 10)
Observatie: O structura do … while este echivalenta cu secventa: instructiuni;
while(expresie)
A instructiuni;
S, asfel incit instructiuni se executa cel putin o data.
6.6. Alte functii si instructiuni
In aceasta categorie amintim:
-a)functia exit cu urmatorul format: void exit(int cod); functie care isi are prototipul in stdlib.h sau process.h.
La apelul acestei functii avem:
-se videaza zonele tampon ale fisierelor deschise in scriere
-se inchid toate fisierele deschise
-se intrerupe executia programului. Parametrul cod definit de utilizator prcizeaza:
-valoarea cod = 0, terminare normala a executiei programului
-valoarea cod ? 0, terminare cu eroare (tratata de SO)
-b)instructiunea continue, cu urmatorul format: continue;
Instructiunea se utilizeaza doar in corpul unui ciclu permitind abandonarea
iteratiei curente.
Exemplu:
…
while(l-- > 0)
A x=f(l); if(x == 1) continue; y= x*x;
S
Efectul instructiunii este urmatorul:
-in ciclurile while si do,…, while, se abandoneaza iteratia curenta si
se trece la evaluarea expresiei care stabileste continuarea ciclului
-in ciclul for, se abandoneaza iteratia curenta si se trece la executia pasului
de reinitializare.
-c)instructiunea break, are urmatorul format: break;
Aceasta instructiune se foloseste in interiorul unui ciclu si are rolul de a
termina executia ciclului in al carei corp este inclusa, executia fiind data
primei instructiuni din afara ciclului respectiv.
Exemplu:
… for(l=0;l < 10; l++)
A if (test(l)) printf(“Test %d OK”,l);// int test(int) e o functie
ce returneaza 1 daca testul este OK si 0 daca este eronat else A printf(“Test eronat %d”,l); break;S
S
-d)instructiunea return, are urmatoarele formate: return; sau return expresie; si are rolul de a termina executia unei functii in care apare, redind controlul
functiei apelante. Daca instructiunea returneaza expresie, ea trebuie sa corespunda
cu tipul functiei care se returneaza sau daca este posibil are loc procesul
de conversie automata.
Observatie:
Daca intr-o functie nu apare instructiunea return atunci controlul revine automat
functiei apelante si anume dupa urmatoarea instructiune de apel a functiei.
Valoarea returnata este nedefinita si in aceste cazuri functia ar trebui declarata
de tip void.
Exemplu: double factorial (int n)
A double f; int l; if (n < 0 || n >170) return -1.0; for(l=2,f=1.0; l <= n; l++) f* = l; return f;
S
-e)instructiunea goto, are urmatorul format: goto nume; unde nume este o eticheta care trebuie sa fie prezenta undeva in program sub
forma: nume: instructiune;
Exemplu: if(coderr > 0) goto iesire;
…. iesire: return (coderr);
7. OPERATORI SI EXPRESII
Prin expresie intelegem un operand sau mai multi legati prin operatori si
care respecta regulile algebrei.
Ca si operand putem avea:
-o constanta
-o constanta simbolica
-numele unei variabile simple
-numele unui tablou
-numele unei structuri
-numele unui tip
-numele unei functii
-referirea la elementele unui tablou (variabila cu indici)
-referirea la elementele unei structuri
-apelul unei functii
-expresie inclusa in paranteze rotunde.
Unui operand ii corespunde un anumit tip si o anumita valoare.
Operatorii pot fi:
-unari, cind se aplica la un singur operand
-binari, cind se aplica la operandul care-l precede si la cel care-l urmeaza
imediat.
Limbajul C++ are si alti operatori care vor fi prezentati separat. Operatorii
limbajului C se pot grupa pe clase astfel:
-aritmetici
-de relatie si de egalitate
-logici, etc.
O expresie poate folosi operatori din clase diferite, la evaluarea ei tinind
cont de:
-precedenta (prioritate)
-asociativitate
-regula conversiilor implicite.
Precedenta (prioritatea) determina ordinea de efectuare a operatiilor intr-o
expresie cu diversi operatori.
Asociativitatea indica ordinea de efectuare a operatiilor intr-o secventa de
operatii ce au aceiasi precedenta.
7.1. Operatori aritmetici
Acesti operatori sunt folositi la calcule cu date de diferite tipuri predefinite.
Ei pot fi:
-a)unari, + (fara efect), - (negativare). Se asociaza de la dreapta spre stinga
fata de cei binari care se asociaza de la stinga la dreapta.
-b)binari, care pot fi:
-multiplicativi,
*, inmultire cei doi operanzi vor fi inmultiti
/, impartire, primul operand va fi divizat la al doilea. Daca sunt intregi rezultatul
va fi partea intreaga a citului
%, modulo, doar pentru operanzi intregi si are ca si rezultat restul impartirii
intregi
-aditivi,
+, adunare
-, scadere, ca si operatori din aritmetica.
Operatorii unari sunt mai prioritari decit cei cei binari si cei multiplicativi
mai prioritari decit cei aditivi.
Regula conversiilor implicite se aplica cind un operator binar se aplica la
operanzi de tipuri diferite pe principiul “inferior” convertit la
“superior”, rezultatul este “superior”.
De asemenea inainte de toate, operanzii de tip char si enum se convertesc in
int.
Exemplu: int l=10, j=3, n; double x=2.0, y; y=x*l; //20.0 n=l/j; //3 n=l%j; //1 n=l+j; //13 n=l-j; //7
7.2. Operatori de relatie si egalitate
Acesti operatori testeaza primul operand fata de al 2-lea pentru a determina
daca relatia este adevarata. Rezultatul este 1 pentru True si 0 pentru False,
astfel incit tipul rezultatului este int. acesti operatori pot fi:
-a)de relatie, care sunt:
<
<=
>
>=, modul de utilizare fiind:
E1 op_relatie E2 cu valore 0 sau 1 functie de rezultat.
Acesti operatori au aceiasi prioritate intre ei dar mai mica decit a celor aditivi. b)de egalitate, care sunt:
==, egal
!=, diferit, operatori care au prioritate mai mica ca cei de relatie.
Modul de utilizare a acestor operatori este:
E1 op_egalitate E2 cu valore 0 sau 1 functie de rezultat, adica 1 sau ? 0 pentru
True, respectiv 0 pentru False, tipul rezultatului fiind int.
Exemplu: int x=0, y=0;//atunci putem evalua astfel urmatorii operatori: x < y //=0 x > y //=0 x <=y //=1 x >=y //=1 x ==y //=1 x != y //=0
7.3. Operatori logici
Acesti operatori pot fi:
-a)pe operand (normali) de urmatoarele tipuri:
-!, negatia logica, ce este operator unar si care se utilizeaza astfel:
!operand = 0 (False), daca operand ? 0
!operand = 1 (True), daca operand = 0.
Acesta este un operand care are aceiasi prioritate cu ceilalti operatori unari.
-&&, si logic, este operator care are prioritate mai mica decit cei
de egalitate si se utilizeaza astfel:
E1 && E2, si are valoarea 1 (True) daca E1 si E2 sunt ambele True in rest are valoarea 0 (False).
-||, sau logic, este operator care are prioritatea mai mica decit &&
si se utilizeaza astfel:
E1 || E2 care are valoarea 0 (False) daca ambele expresii E1 si E2 au valoarea
0 (False). In rest expresia are valoarea 1 (True).
Operatorii || si && se evalueaza de la stinga la dreapta pina cind este
necesar, putind sa nu evaluam pina la capat daca valoarea este decisa inainte
de a ajunge la capatul evaluarii.
Exemplu: int x,y,a,b;
… if (x < y && y < z) printf(“ x < z”);
… if (x == y || x == z) printf(“x =y V x = z);
… a=0;b=5; if (!a && b) printf(“Valoare True”); else printf(“Valoare False”);
-b)pe biti, care se aplica la date de tip intreg bit cu bit si se extind daca
este necesar de la 16 la 32 de biti. Acesti operatori sunt:
-I, complement fata de unu, care are aceiasi prioritate cu ceilalti operatori
unari, schimbind fiecare bit 1 al operatorului in 0 respectiv 0 in 1.
Exemplu:
1234 = 1024 +
128+
64+
16+
2, adica are reprezentarea binara 10011010010 iar ca un intreg pe 16 biti va
arata astfel:
0000010011010010 si
I1234 va arata astfel:
1111101100101101
-<<, deplasare la stinga a valorii primului operand cu un numar de pozitii
egal cu valoarea celui de-al doilea operand, forma de utilizare fiind: op1 << op2. Este echivalent cu inmultirea cu puteri ale lui 2.
Exemplu:
. a << 3 este echivalent cu a*8
->>, deplasare la dreapta a valorii primului operand cu un numar de pozitii
egal cu valoarea celui de-al doilea operand, forma de utilizare fiind: op1 >> op2. Este echivalent cu impartirea cu puteri ale lui 2.
Exemplu:
. a >> 4 este echivalent cu a/16
Prioritatea operatorilor de deplasare este mai mica decit a celor aditivi si
mai mare ca a celor relationali.
-&, si logic pe biti, se executa bit cu bit coform lui SI-LOGIC avind prioritate
mai mica a celor de egalitate. Este folosit la lucru cu masti.
Exemplu:
. a & 0377 este echivalent cu pastrarea octetului cel mai putin semnificativ
al variabilei a.
-^, sau exclusiv pe biti, se executa bit cu bit coform lui SAU-EXCLUSIV avind
prioritate imediat mai mica a lui &, si logic pe biti. Este folosit pentru
a anula sau seta diferiti biti.
Exemplu: int a; a^a, da valoarea =0 a^1, daca a este impar seteaza pe zero ultimul bit adica il face par iar daca
a este par seteaza pe 1 ultimul bit, facind numarul impar.
-|, sau logic pe biti, se executa bit cu bit coform lui SAU-LOGIC avind prioritate
imediat mai mica a lui ^, sau exclusiv pe biti si mai mare decit a operatorului
&& si logic. Este folosit pentru a seta diferiti biti.
Exemplu: int a; a|1, ne da o valoare pentru a unde ultimul bit este totdeauna 1.
7. Operatori de atribuire (asignare)
Principalii operatori de asignare sunt:
-a)asignare simpla, care se noteaza prin carcterul = si are forma: v = (expresie) unde v este o variabila simpla, referinta la un element de tablou
sau de structura.
Se asociaza de la dreapta la stinga astfel: vn=…=v1=v=expresie; //asignarea facindu-se mai intii v=expresie
si apoi se asociaza lui v1 apoi v2 si tot asa pina la vn.
-b)asignare compusa, caz in care pentru atribuire in afara de = se mai foloseste
si forma: operator=, unde operator poate fi:
-binar aritmetic
-logic pe biti, si deci poate fi
/ % * - + << >> & ^ | .
Structura: v operator = expresie este echivalenta cu v = v operator (expresie)
Exemplu: int a,l; a=17; l=l+3; l+=9;
-c)incrementare si decrementare, sunt operatori unari si au aceiasi prioritate
ca si ceilalti operatori unari ai lui C. Acestia sunt ++ si --, putind fi postfixati,
respectiv prefixati.
Exemplu: int y, x=3, z=3; y=++x; //y=4, x=4 y=z++; //y=3, z=4
-d)asignare generala, se compun din urmatorii operatori:
++, operator unar de incrementare
--, operator unar de decrementare
=, asignare simpla
*=, asignare si multiplicare
/=, asignare si impartire
%=, asignare si modulo
+=, asignare si adunare
-=, asignare si scadere
<<=, asignare si deplasare stinga
>>=, asignare si deplasare dreapta
&=, asignare si SI la nivel de bit
|=, asignare si SAU la nivel de bit
^=, asignare si SAU EXCLUSIV la nivel de bit
7.5. Operatori de fortare a tipului sau de conversie explicita (cast)
Operatorul de fortare a tipului, (cast) are urmatoarea forma:
(tip) operand, prin care valoarea operandului se converteste la tipul indicat.
Este folosit mai ales in C++.
Exemplu: int a; double x,z; x=2.0; a=5; z= (double)a/x;//2.5 z= a/ (int)x;//2.0
7.6. Operatorul de dimensiune
Formatul operatorului de determinare a dimensiunii este: sizeof data sau sizeof (tip), determinind dimensiunea in octeti a unei date sau a unui tip data poate fi:
-un nume de variabila simpla
-un nume de tablou
-un nume de structura
-referire la un element de tablou
-referire la elementul unei structuri tip poate fi:
-un cuvint cheie sau cuvintele cheie ale unui tip predefinit
-o constructie care predefineste un tip.
Daca data este:
-numele unei variabile simple, rezultatul este numarul de octeti alocati variabilei
respective
-numele unui tablou, rezultatul va fi numarul de octeti a zonei de memorie alocata
tabloului
-numele unei structuri, rezultatul va fi numarul de octeti a zonei de memorie
alocate structurii.
Prioritatea este cea a operatorilor unari din C.
Exemplu: int x,y; y=sizeof x; //2 long double za7i; y=sizeof za3i; //10 y=sizeof (z); //70 y=sizeof (long double); //10
7.7. Operatori de adresare (&, referentiere) si de indirectare (*, dereferentiere)
Operatorul de adresare este un operator unar si se noteaza prin &. Acest
operator se aplica pentru a determina adresa de inceput a zonei de memorie alocata
unei date, adica pune la dispozitie adresa operandului.
Rezultatul operatorului & este un pointer la operand.
Daca nume este un operand (variabila simpla, nume de tablou, structura etc.)
atunci:
&nume, reprezinta modul de utilizare a acestui operand, valoarea putind
fi atribuita unei variabile de tip pointer.
Daca nume este numele unui tablou, atunci &nume are ca si valoare adresa
de inceput a zonei de memorie alocata tabloului, la fel ca si nume.
Acest operator este un operator unar avind aceiasi prioritate cu ceilalti operatori
unari.
Operatorul de indirectare, *, (dereferentiere) este un operator unar si permite
accesarea unei valori indirect prin intermediul unui pointer.
Operandul asupra caruia se aplica trebuie sa fie o valoare pointer.
Rezultatul operatiei este valoarea pe care pointeaza (puncteaza, o adreseaza)
operandul, adica operatorul * permite accesul la continutul unei zone de memorie
definita de adresa de inceput a ei.
Tipul rezultatului este tipul adresat de operandul pointer.
Daca valoarea pointer-ului este nula, atunci rezultatul este neprevazut.
Exemplu: int x, *pa; //pa este o variabila pointer spre o valoare de intreg int aa20i; pa=&aa5i; //pa este adresa celui de a-l saselea element din tablou x=*pa; // x=continutul de la adresa lui pa, adica valoarea celui de al 6-lea
element, in acest caz mult mai simplu ar fi x=aa5i
Observatie: Operatorul de adresare si cel de indirectare se anuleaza reciproc
daca sunt unul dupa celalalt
7.8. Operatorii paranteza
Acesti operatori pot fi:
-a)parantezele rotunde, ( ), care se folosesc la:
-a include o expresie care urmeaza a fi evaluata
-la apelul functiilor, cind parametrii efectivi sunt inclusi intre paranteze
rotunde care sunt considerate in acest caz operatori de apel de functie.
Observatie:
Operandului rezultat din includerea unei expresii intre paranteze nu i se pot
aplica operatorii de incrementare, decrementare, adresare.
-b)paranteze patrate, a i, includ expresii care reprezinta indici si se numesc
operatori de indexare.
Operatorii paranteza au prioritatea maxima dupa ei urmind operatorii unari.
7.9. Operatori conditionali
Operatorii conditionali, ? si :, permit construirea de expresii a caror valoare
sa depinda de valoarea unei conditii. Conditia este o expresie care poate avea
doua valori, True (?0) sau False (=0).
Acesti operatori sunt ? si :, iar expresia conditionala are formatul:
E1 ? E2 : E3, unde E1, E2, E3 sunt expresii.
Evaluarea se face astfel:
-se determina valoarea lui E1
-daca E1 ? 0, adica e True, atunci valoarea si tipul expresiei conditionale
coincide cu E2, altfel cu E3.
Acesti operatori au prioritate mai mica decit SAU-LOGIC, ||, si mai mare decit
a operatorului de atribuire. v = E1 ? E2 : E3; este o expresie de atribuire, operatorii conditionali asociindu-se de la dreapta
la stinga.
Exemplu: int l,j;
… j=(l < 0) ? (-l) : (l); // j=abs(l)
7.10. Operatorul virgula (evaluare seventiala)
Operatorul virgula, , , leaga doua expresii in una singura astel: exp1,exp2.
Acest operator are cea mai mica prioritate dintre toti operatorii, fiind deci
imediat mai mica decit a operatorilor de atribuire.
Valoarea si tipul expresiei rezultate coincide cu valoarea si tipul ultimei
expresii, deci in acest caz cu exp2.
Acest operator este folosit atunci cind intr-un punct dintr-un program se face
un calcul complex exprimat prin mai multe expresii.
Exemplu: for(l=j=1; l+j < 20; l+=l, j--) //este folosit in cadrul expresiei de reinitializare
a ciclului f(x, y+2, z); //in acest caz virgula este ca separator si nu ca operator g((x--,y+2), z); //g are 2 argumente, primul este rezultatul evaluarii secventiale
din paranteza avind valoarea si tipul expresiei y+2, al doilea fiind z.
7.11. Alti operatori ai limbajului C
Operatorii ., (punct) si ->, (sageata) se folosesc pentru a accesa componentele
unei structu