Responsabili:
În urma parcurgerii acestui laborator studentul va fi capabil să:
Tipurile de date reprezintă tipul de informație care poate fi stocat într-o variabilă. Un tip de data definește atât gama de valori pe care o poate lua o variabilă de un anume tip cât și operațiile care se pot efectua asupra ei. În continuare sunt prezentate tipurile fundamentale ale limbajului C, împreună cu o scurtă descriere a acestora:
char
- reprezentat printr-un număr pe 8 biți (un byte). Poate fi echivalent fie cu signed char
, fie cu unsigned char
. Vezi observația de mai jos cu privire la acest lucru. Este folosit în general pentru reprezentarea caracterelor ASCII.int
- stochează numere întregi. Lungimea sa (și implicit plaja de valori) este dependentă de compilator si sistemul de operare considerat. În general, pe Linux, int
se reprezintă pe 32 de biți (deci 4 bytes). În acest caz, poate memora numere din intervalul [–2.147.483.648; 2.147.483.647].float
- reprezintă un număr real stocat în virgulă mobilă, în gama de valori 3.4E+/-38. În general respectă formatul IEEE 754 single-precision, ceea ce înseamnă că dimensiunea sa va fi 4 (octeți) și numărul va avea cel puțin 7 zecimale exacte.double
- reprezinta un număr real stocat în virgulă mobilă, în gama de valori 1.7E+/-308. În general respectă formatul IEEE 754 double-precision, ceea ce înseamnă că dimensiunea sa va fi 8 (octeți) și numărul va avea cel puțin 15 zecimale exacte.Acestor tipuri fundamentale li se mai pot adăuga un număr de specificatori, după cum urmează:
short
- aplicabil doar pentru int
. Tipul rezultat are cel puțin 16 biți.long
- aplicabil pentru int
și double
. long int
se garantează că are cel puțin 32 biți. Legat de long double
se garantează doar că este mai mare sau egal ca dimensiune decât double
, care la rândul lui este mai mare sau egal decât float
.și
signed
- aplicabil pentru int
și char
. O variabilă declarată int
este implicit signed
. Cuvântul cheie există în acest caz doar pentru cazuri în care vrem să spunem acest lucru explicit. Aplicat pe char
(⇒ signed char
), ne garantează faptul că acea variabilă va putea avea orice valoare din intervalul [-128; 127].unsigned
- precizează faptul că valoarea variabilei este pozitivă. Aplicabil doar tipurilor întregi.
Cei 4 specificatori au fost împărțiți în 2 grupuri de specificatori complementari. Asta înseamnă că expresia long signed int a;
este corectă. La fel este și unsigned short int b;
. Definiția short long int c;
nu este însă corectă. De asemenea, nu oricare specificator din prima categorie cu unul din a doua se pot combina. De exemplu, long signed char d;
și long unsigned double e;
nu sunt corecte.
Uneori ne dorim să folosim tipuri a căror dimensiune este exact specificată (ca în cazul lucrului cu struct-uri, care va fi discutat într-un laborator viitor). Pentru asta, putem folosi tipurile definite în headerul <stdint.h>
.
Câteva exemple sunt următoarele: int8_t
, int16_t
, int64_t
, uint32_t
. Pentru o listă completă consultați documentația oficială (online) a limbajului.
for
, cel mai probabil tipul pe care îl vreți este int
.
Determinarea corectă a tipurilor de date care vor fi folosite este esențială pentru securitatea și buna funcționare a aplicațiilor pe care le scrieți. În cazul în care valoarea conținută de o variabilă depașește limitele impuse de tipul de date folosit, se produce așa-numit-ul over-flow care poate cauza erori aparent inexplicabile. (Ca o anecdotă, în fiecare an (până acum trei sau patru ani), Bill Gates primea de la FISC o scrisoare prin care era somat să iși platească taxele, deoarece apărea in evidențele lor ca având datorii însemnate. Asta deoarece valoarea averii lui (mult peste 4.000.000.000$) producea un overflow în softul folosit de către FISC. În final situația a fost soluționată, introducând un câmp special pentru el în softul folosit. (A modifica softul peste tot ar fi introdus un plus de stocare nejustificat pentru fiecare din cei aproximativ 300.000.000 de cetațeni ai SUA.) )
Operatorii limbajului C pot fi unari, binari sau ternari, fiecare având o precedenţă şi o asociativitate bine definite. Tabelul următor sintetizează operatorii limbajului C. Operatorii sunt prezentaţi în ordine descrescătoare a priorităţii.
Precedenţă | Operator | Descriere | Asociativitate |
---|---|---|---|
1 | [] | Indexare | stanga-dreapta |
. şi -> | Selecţie membru (prin structură, respectiv pointer) | stânga-dreapta | |
++ şi -- | Postincrementare/postdecrementare | stânga-dreapta | |
2 | ! | Negare logică | dreapta-stânga |
~ | Complement faţă de 1 pe biţi | dreapta-stânga | |
++ şi -- | Preincrementare/predecrementare | dreapta-stânga | |
+ şi - | + şi - unari | dreapta-stânga | |
* | Dereferenţiere | dreapta-stânga | |
& | Operator adresă | dreapta-stânga | |
(tip) | Conversie de tip | dreapta-stânga | |
sizeof() | Mărimea în octeţi | dreapta-stânga | |
3 | * | Înmulţire | stânga-dreapta |
\/ | Împărţire | stânga-dreapta | |
% | Restul împărţirii | stânga-dreapta | |
4 | + şi - | Adunare/scădere | stânga-dreapta |
5 | << si >> | Deplasare stânga/dreapta a biţilor | stânga-dreapta |
6 | < | Mai mic | stânga-dreapta |
<= | Mai mic sau egal | stânga-dreapta | |
> | Mai mare | stânga-dreapta | |
>= | Mai mare sau egal | stânga-dreapta | |
7 | == | Egal | stânga-dreapta |
!= | Diferit | stânga-dreapta | |
8 | & | ŞI pe biţi | stânga-dreapta |
9 | ^ | SAU-EXCLUSIV pe biţi | stânga-dreapta |
10 | | | SAU pe biţi | stânga-dreapta |
11 | && | ŞI logic | stânga-dreapta |
12 | || | SAU logic | stânga-dreapta |
13 | ?: | Operator condiţional | dreapta-stânga |
14 | = | Atribuire | dreapta-stânga |
+= şi -= | Atribuire cu adunare/scădere | dreapta-stânga | |
*= şi /= | Atribuire cu multiplicare/împărţire | dreapta-stânga | |
%= | Atribuire cu modulo | dreapta-stânga | |
&= si |= | Atribuire cu ŞI/SAU | dreapta-stânga | |
^= | Atribuire cu SAU-EXCLUSIV | dreapta-stânga | |
<<= şi >>= | Atribuire cu deplasare de biţi | dreapta-stânga | |
15 | , | Operator secvenţa | stânga-dreapta |
Trebuie avută în vedere precedenţa operatorilor pentru obţinerea rezultatelor scontate. Dacă unele tipuri de precedenţă (cum ar fi cea a operatorilor artimetici) sunt evidente şi nu prezintă (aparent) probleme (şi datorită folosirii lor dese), altele pot duce la erori greu de găsit. De exemplu, următorul fragment de cod nu produce rezultatul dorit, deoarece:
if (flags & MASK == 0) { ... }
se evaluează mai întai egalitatea care produce ca rezultat (0 pentru False, și 1 pentru True) după care se aplică Și pe biți între flags și 1.
Pentru a obţine rezultatul dorit se vor folosi parantezele:
if ((flags & MASK) == 0) { ... }
acum mai întâi se va face ȘI pe biți între flags și MASK, după care se verifică egalitatea.
O expresie este o secventă de operanzi și operatori (validă din punct de vedere al sintaxei limbajului C) care realizează una din funcțiile: calculul unei valori, desemnarea unui obiect (variabilă) sau funcţii sau generarea unui efect lateral.
O altă greşeală frecventă este utilizarea greşită a operatorilor = şi ==. Primul reprezintă atribuire, al doilea comparaţie de egalitate. Apar deseori erori ca:
if (a = 2) { ... }
Compilatorul consideră condiţia corectă, deoarece este o expresie validă în limbajul C care face atribuire, care se evaluează mereu la o valoare nenulă.
Fișierul antet math.h
conține un set de funcții matematice des utilizate în programe. Câteva dintre acestea sunt:
Antet | Descriere |
---|---|
double asin(double arg); | Calculează arcsinusul/arccosinusul valorii arg; rezultatul este măsurat în radiani |
double atan(double arg); | Calculează arctangenta valorii arg, respectiv a fracției y/x |
double floor(double num); | Întoarce cel mai mare întreg mai mic sau egal cu num (partea întreagă inferioară) |
double ceil(double num); | Întoarce cel mai mic întreg mai mare sau egal cu num (partea întreagă superioară) |
double sin(double arg); | Calculează sinusul/cosinusul/tangenta parametrului arg, considerată în radiani |
double sinh(double arg); | Calculează sinusul/cosinusul/tangenta hiperbolică a parametrului arg |
double exp(double arg); | Întoarce valoarea e arg |
double pow(double base, double exp); | Întoarce valoarea base exp |
double log(double num); | Calculează logaritmul natural (de bază e) al valorii num |
double log10(double num); | Calculează logaritmul în baza 10 al parametrului |
double sqrt(double num); | Calculează radăcina pătrată a parametrului |
double fmod(double x, double y); | Întoarce restul împarțirii lui x la y |
double fabs(double arg); | Întoarce valoarea absolută a lui arg |
Următoarele două probleme vă vor fi date de asistent în cadrul laboratorului.
START
(cu interval de 1 secundă între fiecare număr). Exemplu: 3 //așteaptă o secundă 2 //așteaptă o secundă 1 //așteaptă o secundă START
0x1234
de exemplu) si rulați din nou programul de câteva ori la rând. Ce observaţi? Care e explicaţia?Va fi dat de către asistent.