Diferență între revizuiri ale paginii „PC Laborator 4”
(Nu s-au afișat 64 de versiuni intermediare efectuate de alți 4 utilizatori) | |||
Linia 2: | Linia 2: | ||
− | Familiarizarea cu noțiunile de bază ale limbajului C: tipuri de date, operatori, dar și folosirea corectă a acestora. | + | Familiarizarea cu noțiunile de bază ale limbajului C: tipuri de date numerice, operatori aritmetici, operatori pe biți dar și folosirea corectă a acestora. |
− | == Tipuri de date == | + | == Tipuri de date numerice == |
− | Tipurile de date fundamentale ale limbajului C sunt | + | <div class="regula">'''<font color="red"> Observatie:</font>''' Bit-ul reprezintă cea mai mică unitate de informaţie dintr-un calculator. Denumirea de bit provine de la „binary digit” adică număr binar. Sistemul binar este un sistem de numeraţie unde totul se reprezintă doar cu 1 şi 0. Simbolul pentru un bit este "b",a nu se confunda cu byte "B" care reprezintă o grupare de 8 biți.</div> |
− | + | ||
− | + | === Tipuri de date întregi === | |
+ | |||
+ | Tipurile de date întregi fundamentale ale limbajului C sunt <code>char</code> și <code>int</code>. | ||
+ | |||
+ | <div class="regula">'''<font color="red"> Observatie:</font>''' Specificația limbajul C nu forțează tipurile de date să aibă o dimensiune fixă. Prin urmare ele pot avea diferite limite, în funcție de procesor și compilator. De aici înainte, toate dimensiunile specificate sunt pentru compilatorul GCC ce rulează pe un procesor compatibil x86, pe 64 de biți.</div> | ||
{| class="wikitable" | {| class="wikitable" | ||
Linia 14: | Linia 18: | ||
|- | |- | ||
| style="text-align: center;" |Tip | | style="text-align: center;" |Tip | ||
− | | style="text-align: center;" | | + | | style="text-align: center;" |Număr de biți |
| style="text-align: center;" |Domeniu | | style="text-align: center;" |Domeniu | ||
|- | |- | ||
| char | | char | ||
| style="text-align: center;" | 8 | | style="text-align: center;" | 8 | ||
− | | style="text-align: center;" | - | + | | style="text-align: center;" | -128 ... +127 |
|- | |- | ||
| int | | int | ||
− | | style="text-align: center" | 16 | + | | style="text-align: center" | 32 |
− | | style="text-align: center;" | - | + | | style="text-align: center;" | -2,147,483,648 ... +2,147,483,647 |
+ | |} | ||
+ | |||
+ | Tipurile fundamentale pot fi precedate de diferiţi modificatori. Un '''modificator''' se utilizează pentru a adapta cât mai convenabil tipul de bază la situație. | ||
+ | |||
+ | ==== Modificatori ==== | ||
+ | |||
+ | * '''signed''' (implicit) - tip de dată cu semn, utilizabil excusiv pentru numere întregi, face ca intervalul de definiție să fie între [-2<sup>n-1</sup>:2<sup>n-1</sup>-1]; | ||
+ | * '''unsigned''' - tip de dată fără semn, utilizabil excusiv pentru numere întregi, face ca intervalul de definiție să fie între [0:2<sup>n</sup>-1]; | ||
+ | * '''long''' - de obicei, dublează domeniul de definiție pentru '''int'''; de exemplu un '''long int''' va avea 64 de biți în loc de 32; | ||
+ | * '''short''' - de obicei, înjumătățește domeniul de definiție pentru '''int''', adică rezultatul este un tip de dată pe 16 biți. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! colspan="3" | Folosirea modificatorilor | ||
+ | |- | ||
+ | | style="text-align: center;" |Tip | ||
+ | | style="text-align: center;" |Număr de biți | ||
+ | | style="text-align: center;" |Domeniu | ||
+ | |- | ||
+ | | unsigned char | ||
+ | | style="text-align: center;" | 8 | ||
+ | | style="text-align: center;" | 0 ... 255 | ||
+ | |- | ||
+ | | unsigned long int | ||
+ | | style="text-align: center" | 64 | ||
+ | | style="text-align: center;" | 0 .. 18,446,744,073,709,551,615 | ||
+ | |} | ||
+ | |||
+ | Diferenţa dintre întregii signed şi unsigned constă în interpretarea diferită a bitului semnificativ (adică cel mai din stânga). | ||
+ | Pentru un întreg signed, se va considera bitul semnificativ ca fiind bit de semn. Dacă acest bit este 0 atunci numărul este pozitiv iar dacă este 1 atunci este negativ. | ||
+ | Modul de reprezentare a valorilor negative se face folosind convenția complement față de 2. | ||
+ | |||
+ | === Tipuri în virgulă mobilă === | ||
+ | |||
+ | Tipurile de date în virgulă mobilă ale limbajului C sunt <code>float</code>, <code>double</code> și <code>long double</code>. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! colspan="3" | Tipuri fundamentale | ||
+ | |- | ||
+ | | style="text-align: center;" |Tip | ||
+ | | style="text-align: center;" |Număr de biți | ||
+ | | style="text-align: center;" |Domeniu | ||
|- | |- | ||
| float | | float | ||
| style="text-align: center;" | 32 | | style="text-align: center;" | 32 | ||
− | | style="text-align: center;" | Precizie | + | | style="text-align: center;" | Precizie 4 zecimale |
|- | |- | ||
| double | | double | ||
| style="text-align: center;" | 64 | | style="text-align: center;" | 64 | ||
− | | style="text-align: center;" | Precizie | + | | style="text-align: center;" | Precizie 8 zecimale |
+ | |- | ||
+ | | long double | ||
+ | | style="text-align: center;" | 80 | ||
+ | | style="text-align: center;" | Precizie 16 zecimale | ||
+ | |||
|} | |} | ||
− | |||
− | |||
− | |||
<div class="regula">'''<font color="red"> Observatie:</font>''' Principalul dezavantaj al reprezentării în virgulă fixă este faptul că, dacă un număr nu mai încape în spaţiul de biţi rezervat, se pierd cifrele cele mai semnificative.</div> | <div class="regula">'''<font color="red"> Observatie:</font>''' Principalul dezavantaj al reprezentării în virgulă fixă este faptul că, dacă un număr nu mai încape în spaţiul de biţi rezervat, se pierd cifrele cele mai semnificative.</div> | ||
Linia 44: | Linia 91: | ||
[[Fișier:Mantisa.jpg]] | [[Fișier:Mantisa.jpg]] | ||
− | Unde s este bitul de semn al | + | Unde <code>s</code> este bitul de semn al numărului, cu aceeași convenție ca pentru numere în virgulă fixă (s=0 număr pozitiv și s=1 număr negativ), <code>m</code> este mantisa numărului, reprezentând cifrele semnificative, iar <code>e</code> este exponentul (puterea la care trebuie ridicată baza). |
− | m este mantisa | ||
− | |||
− | |||
− | + | Valoarea numărului fracționar reprezentat în virgulă mobilă este data de expresia: | |
− | < | + | <math>valoare=-1^s \times m \times baza^e</math> |
− | </ | ||
− | == | + | <div class="regula">'''<font color="red"> Observatie:</font>''' Mantisa trebuie să îndeplinească condiția: <math>1 > m \geqslant 1 / baza</math> </div> |
+ | == Tipuri de date de dimensiune fixă în standardul C99 == | ||
− | + | Deoarece există situații când numărul de biți pentru un anumit tip de dată este extrem de important, iar acest număr diferă între procesoare și compilatoare, standardul C99 a introdus următoarele tipuri de date, de dimensiune fixă, care se găsesc în header-ul <code style="color: blue">stdint.h</code>: | |
− | |||
− | |||
− | |||
{| class="wikitable" | {| class="wikitable" | ||
− | ! colspan="3" | | + | ! colspan="3" | Tipuri de dimensiune fixă |
|- | |- | ||
| style="text-align: center;" |Tip | | style="text-align: center;" |Tip | ||
Linia 69: | Linia 110: | ||
| style="text-align: center;" |Domeniu | | style="text-align: center;" |Domeniu | ||
|- | |- | ||
− | | | + | | int8_t |
+ | | style="text-align: center;" | 8 | ||
+ | | style="text-align: center;" | -128 .. +127 | ||
+ | |- | ||
+ | | uint8_t | ||
| style="text-align: center;" | 8 | | style="text-align: center;" | 8 | ||
− | | style="text-align: center;" | 0 ... | + | | style="text-align: center;" | 0 .. 255 |
+ | |- | ||
+ | | int16_t | ||
+ | | style="text-align: center" | 16 | ||
+ | | style="text-align: center;" | -32,768 ... +32,767 | ||
|- | |- | ||
− | | | + | | uint16_t |
| style="text-align: center" | 16 | | style="text-align: center" | 16 | ||
− | | style="text-align: center;" | 0 ... 4,294,967,295 | + | | style="text-align: center;" | 0 ... +65,535 |
+ | |- | ||
+ | | int32_t | ||
+ | | style="text-align: center;" | 32 | ||
+ | | style="text-align: center;" | -2,147,483,648 .. 2,147,483,647 | ||
+ | |- | ||
+ | | uint32_t | ||
+ | | style="text-align: center;" | 32 | ||
+ | | style="text-align: center;" | 0 .. 4,294,967,295 | ||
+ | |- | ||
+ | | int64_t | ||
+ | | style="text-align: center;" | 64 | ||
+ | | style="text-align: center;" | -9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807 | ||
+ | |- | ||
+ | | uint64_t | ||
+ | | style="text-align: center;" | 64 | ||
+ | | style="text-align: center;" | 0 .. 18,446,744,073,709,551,615 | ||
|} | |} | ||
− | + | <div class="sfat">'''<font color="blue">Recomandare:</font>''' Utilizați tipurile de date de dimensiune fixă pentru valorile numerice întregi, tipul de date '''char''' pentru a stoca un caracter și tipurile '''float''', '''double''' și '''long double''' pentru valorile numerice fracționare.</div> | |
− | |||
− | |||
− | |||
− | |||
− | |||
== Operatori == | == Operatori == | ||
− | + | === Operatorii aritmetici === | |
− | * + adunarea | + | * <code>+</code> adunarea |
− | * - scăderea | + | * <code>-</code> scăderea |
− | * * înmulţirea | + | * <code>*</code> înmulţirea |
− | * / împărţirea (rezultatul împărţirii pentru numere reale, câtul împărţirii pentru numere întregi) | + | * <code>/</code> împărţirea (rezultatul împărţirii pentru numere reale, câtul împărţirii pentru numere întregi) |
− | * % modulo (restul împărţirii a două numere întregi) | + | * <code>%</code> modulo (restul împărţirii a două numere întregi) |
− | * ++ incrementarea (mărirea unei valori cu o unitate) | + | * <code>++</code> incrementarea (mărirea unei valori cu o unitate) |
− | * -- decrementarea (micşorarea unei valori cu o unitate) | + | * <code>--</code> decrementarea (micşorarea unei valori cu o unitate) |
Operatorii de incrementare/decrementare sunt folosiţi pentru creșterea/micşorarea unei valori cu o unitate. | Operatorii de incrementare/decrementare sunt folosiţi pentru creșterea/micşorarea unei valori cu o unitate. | ||
Linia 110: | Linia 170: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | === Operatori la nivel de bit === | |
− | * > - | + | Avem şase operatori la nivel de bit,aceștia se aplică tipurilor char,int,long signed/unsigned,iar rezultatul este un întreg. |
− | * > | + | Operatorii la nivel de bit sunt următorii. |
− | * < | + | * <code>~</code> - negare la nivel de bit |
− | * < | + | * <code>&</code> - AND (şi logic) |
− | * | + | * <code>|</code> - OR (sau logic) |
− | * | + | * <code>^</code> - XOR (sau exclusiv) |
− | + | * <code><<</code> - deplasare la stânga | |
− | + | * <code>>></code> - deplasare la dreapta | |
− | |||
− | === | + | ==== Operator de negare be biți (BWNOT) ==== |
+ | Operatorul de negare realizează complementarea biților, biții de 0 se pun 1, iar biții de 1 se pun 0. | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
− | + | int a = 2200; /* 0....0 1000 1001 1000*/ | |
− | + | a = ~a; /* 1....1 0110 0110 0111*/ | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | ==== Operatorul ȘI pe biți (BWAND) ==== | |
− | + | Dorim să aflăm valoarea bitului de pe poziția 2 a numarului 20.Pentru a afla valorea acestui bit se poate realiza operația AND (&) între numărul dorit și un alt număr binar care are doar pe poziția dorită valoarea 1 (în cazul nostru poziția 2),astfel dacă rezultatul este diferit de 0 atunci inițial am avut bitul 1, respectiv 0 dacă bitul a fost 0. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
{| class="wikitable" | {| class="wikitable" | ||
− | |||
− | |||
− | |||
− | |||
− | |||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
Linia 171: | Linia 207: | ||
|1 || 1 || 1 | |1 || 1 || 1 | ||
|} | |} | ||
− | | | + | |
− | + | <syntaxhighlight lang="C"> | |
− | {| class="wikitable" | + | |
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int a = 20; /* 0...0 1 0 1 0 0 */ | ||
+ | int b = 4; /* 0...0 0 0 1 0 0 */ | ||
+ | |||
+ | if (a & b) {/* 0...0 0 0 1 0 0 */ | ||
+ | printf("Rezultatul este diferit de 0\n"); | ||
+ | } else { | ||
+ | printf("Rezultatul are valoarea 0\n"); | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Operatorul SAU pe biți (BWOR) ==== | ||
+ | Dorim să setăm (în 1) valoarea bitului de pe poziția 2 a numarului 20. Pentru a seta valorea acestui bit se poate realiza operația OR (|) între numărul dorit și un alt număr binar care are doar pe poziția dorită valoarea 1 (în cazul nostru poziția 2). | ||
+ | |||
+ | {| class="wikitable" | ||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
Linia 186: | Linia 242: | ||
|1 || 1 || 1 | |1 || 1 || 1 | ||
|} | |} | ||
− | | | + | |
− | + | <syntaxhighlight lang="C"> | |
− | {| class="wikitable" | + | |
+ | int main() { | ||
+ | int a = 20; /* 0...0 1 0 1 0 0 */ | ||
+ | int b = 4; /* 0...0 0 0 1 0 0 */ | ||
+ | int c = a | b; /* 0...0 1 0 1 0 0*/ | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Operatorul SAU EXCLUSIV pe biți (BWXOR) ==== | ||
+ | Dorim să schimbăm valoarea bitului de pe poziția 2 a numarului 20. Pentru a schimba valorea acestui bit se poate realiza operația XOR (^) între numărul dorit și un alt număr binar care are doar pe poziția dorită valoarea 1 (în cazul nostru poziția 2). | ||
+ | |||
+ | {| class="wikitable" | ||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
Linia 200: | Linia 269: | ||
|- bgcolor="#ddffdd" align="center" | |- bgcolor="#ddffdd" align="center" | ||
|1 || 1 || 0 | |1 || 1 || 0 | ||
− | |||
|} | |} | ||
− | |||
− | |||
− | |||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | int main() { | |
− | + | int a = 20; /* 0...0 1 0 1 0 0 */ | |
− | + | int b = 4; /* 0...0 0 0 1 0 0 */ | |
− | + | int c = a ^ b; /* 0...0 1 0 0 0 0*/ | |
− | + | return 0; | |
− | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | === | + | ==== Operatorul de deplasare la stânga ==== |
− | Operatorii de deplasare (<< şi >>) realizează deplasarea biţilor din operandul stâng cu atâtea | + | Operatorii de deplasare (<< şi >>) realizează deplasarea biţilor din operandul stâng cu atâtea poziţii câte sunt indicate de operandul drept. |
− | poziţii câte sunt indicate de operandul drept. | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
− | int a = 255; /* | + | int a = 255; /* 0...0 0000 1111 1111*/ |
− | a = a << 3; /* | + | a = a << 3; /* 0...0 0111 1111 1000*/ |
</syntaxhighlight> | </syntaxhighlight> | ||
<div class="regula">'''<font color="red"> Observatie:</font> '''Deplasarea la stânga (<<) completează la dreapta cu 0, deci biţii din stânga se vor pierde.</div> | <div class="regula">'''<font color="red"> Observatie:</font> '''Deplasarea la stânga (<<) completează la dreapta cu 0, deci biţii din stânga se vor pierde.</div> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Exerciții == | == Exerciții == | ||
Linia 251: | Linia 298: | ||
<ol> | <ol> | ||
<li> Scrieți un program care să citească un număr în virgulă mobilă de la tastatură și să se afișeze, pe linii diferite, în hexazecimal, semnul, mantisa și exponentul. Notă: pentru a putea efectua operații pe biți, operanzii trebuie să fie de tip întreg. Astfel, pentru a interpreta un număr în virgulă mobilă ca secvență de biți, variabila trebuie sa fie de tip int, iar citirea să se facă cu template-ul "%f".</li> | <li> Scrieți un program care să citească un număr în virgulă mobilă de la tastatură și să se afișeze, pe linii diferite, în hexazecimal, semnul, mantisa și exponentul. Notă: pentru a putea efectua operații pe biți, operanzii trebuie să fie de tip întreg. Astfel, pentru a interpreta un număr în virgulă mobilă ca secvență de biți, variabila trebuie sa fie de tip int, iar citirea să se facă cu template-ul "%f".</li> | ||
− | <li> Scrieți un program care să citească de la tastatură un număr întreg fără semn pe | + | <li> Scrieți un program care să citească de la tastatură un număr întreg fără semn pe 8 biți (în bază 10) și să-l afișeze pe ecran în baza doi, folosind operatori de shiftare și mascare.</li> |
<li> Citiți de la tastatură un număr întreg cu semn, pe 32 de biți, apoi negați-l aritmetic și afișați valoarea, fără să folosiți operatorului unar "-" (folosind regulile convenției complement față de 2).</li> | <li> Citiți de la tastatură un număr întreg cu semn, pe 32 de biți, apoi negați-l aritmetic și afișați valoarea, fără să folosiți operatorului unar "-" (folosind regulile convenției complement față de 2).</li> | ||
− | <li> Scrieți un program care să citească un număr întreg pe 8 biți de la tastatură, să numere și să afișeze câți biți de 1 și câți biți 0 are reprezentarea lui binară.</li> | + | <li> Scrieți un program care să citească un număr întreg pozitiv pe 8 biți de la tastatură, să numere și să afișeze câți biți de 1 și câți biți 0 are reprezentarea lui binară.</li> |
<li> Citiți de la tastatură un număr întreg n, calculați și afișați suma numerelor de la 0 la n.</li> | <li> Citiți de la tastatură un număr întreg n, calculați și afișați suma numerelor de la 0 la n.</li> | ||
− | <li> Citiți o valoare de temperatură în grade | + | <li> Citiți o valoare de temperatură în grade Celsius, și afișați pe ecran valoarea acelei temperaturi în Kelvin și grade Fahrenheit. </li> |
<li> Fie o matrice de 8 linii și 10 coloane, cu elementele numerotate de la 0 (elementul din stânga sus) la 79 (elementul din dreapta jos): | <li> Fie o matrice de 8 linii și 10 coloane, cu elementele numerotate de la 0 (elementul din stânga sus) la 79 (elementul din dreapta jos): | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Linia 265: | Linia 312: | ||
Dându-se de la tastatură un index n între 0 si 79, să se afișeze pe ce linie și pe ce coloană este indexul respectiv.</li> | Dându-se de la tastatură un index n între 0 si 79, să se afișeze pe ce linie și pe ce coloană este indexul respectiv.</li> | ||
<li>Dându-se un număr întreg de la tastatură, să se afișeze 0 dacă numărul este impar și 1 dacă este par.</li> | <li>Dându-se un număr întreg de la tastatură, să se afișeze 0 dacă numărul este impar și 1 dacă este par.</li> | ||
− | <li> | + | <li>Dându-se un număr întreg de la tastatură, să se afișeze restul împărțirii numărului la 16, folosind doar operații pe biți.</li> |
+ | <li><code>dificil</code> Folosind doar operații pe biți (fără construcții condiționale), să se calculeze modulul unui număr întreg pe 32 de biți, introdus de la tastatură.</li> | ||
<ol> | <ol> |
Versiunea curentă din 1 iulie 2021 21:27
Obiective
Familiarizarea cu noțiunile de bază ale limbajului C: tipuri de date numerice, operatori aritmetici, operatori pe biți dar și folosirea corectă a acestora.
Tipuri de date numerice
Tipuri de date întregi
Tipurile de date întregi fundamentale ale limbajului C sunt char
și int
.
Tipuri fundamentale | ||
---|---|---|
Tip | Număr de biți | Domeniu |
char | 8 | -128 ... +127 |
int | 32 | -2,147,483,648 ... +2,147,483,647 |
Tipurile fundamentale pot fi precedate de diferiţi modificatori. Un modificator se utilizează pentru a adapta cât mai convenabil tipul de bază la situație.
Modificatori
- signed (implicit) - tip de dată cu semn, utilizabil excusiv pentru numere întregi, face ca intervalul de definiție să fie între [-2n-1:2n-1-1];
- unsigned - tip de dată fără semn, utilizabil excusiv pentru numere întregi, face ca intervalul de definiție să fie între [0:2n-1];
- long - de obicei, dublează domeniul de definiție pentru int; de exemplu un long int va avea 64 de biți în loc de 32;
- short - de obicei, înjumătățește domeniul de definiție pentru int, adică rezultatul este un tip de dată pe 16 biți.
Folosirea modificatorilor | ||
---|---|---|
Tip | Număr de biți | Domeniu |
unsigned char | 8 | 0 ... 255 |
unsigned long int | 64 | 0 .. 18,446,744,073,709,551,615 |
Diferenţa dintre întregii signed şi unsigned constă în interpretarea diferită a bitului semnificativ (adică cel mai din stânga). Pentru un întreg signed, se va considera bitul semnificativ ca fiind bit de semn. Dacă acest bit este 0 atunci numărul este pozitiv iar dacă este 1 atunci este negativ. Modul de reprezentare a valorilor negative se face folosind convenția complement față de 2.
Tipuri în virgulă mobilă
Tipurile de date în virgulă mobilă ale limbajului C sunt float
, double
și long double
.
Tipuri fundamentale | ||
---|---|---|
Tip | Număr de biți | Domeniu |
float | 32 | Precizie 4 zecimale |
double | 64 | Precizie 8 zecimale |
long double | 80 | Precizie 16 zecimale |
Un număr este reprezentat în virgulă mobilă printr-un cuvant de n biți conținând semn, mantisă și exponent sub următoarea formă:
Unde s
este bitul de semn al numărului, cu aceeași convenție ca pentru numere în virgulă fixă (s=0 număr pozitiv și s=1 număr negativ), m
este mantisa numărului, reprezentând cifrele semnificative, iar e
este exponentul (puterea la care trebuie ridicată baza).
Valoarea numărului fracționar reprezentat în virgulă mobilă este data de expresia:
<math>valoare=-1^s \times m \times baza^e</math>
Tipuri de date de dimensiune fixă în standardul C99
Deoarece există situații când numărul de biți pentru un anumit tip de dată este extrem de important, iar acest număr diferă între procesoare și compilatoare, standardul C99 a introdus următoarele tipuri de date, de dimensiune fixă, care se găsesc în header-ul stdint.h
:
Tipuri de dimensiune fixă | ||
---|---|---|
Tip | Numar de biti | Domeniu |
int8_t | 8 | -128 .. +127 |
uint8_t | 8 | 0 .. 255 |
int16_t | 16 | -32,768 ... +32,767 |
uint16_t | 16 | 0 ... +65,535 |
int32_t | 32 | -2,147,483,648 .. 2,147,483,647 |
uint32_t | 32 | 0 .. 4,294,967,295 |
int64_t | 64 | -9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807 |
uint64_t | 64 | 0 .. 18,446,744,073,709,551,615 |
Operatori
Operatorii aritmetici
+
adunarea-
scăderea*
înmulţirea/
împărţirea (rezultatul împărţirii pentru numere reale, câtul împărţirii pentru numere întregi)%
modulo (restul împărţirii a două numere întregi)++
incrementarea (mărirea unei valori cu o unitate)--
decrementarea (micşorarea unei valori cu o unitate)
Operatorii de incrementare/decrementare sunt folosiţi pentru creșterea/micşorarea unei valori cu o unitate.
a++ / ++a - incrementare a-- / --a - decrementare
De asemenea se pot folosi instrucțiuni de pre sau post incrementare/decrementare.
POST-incrementare: x = a++;
x = a;
a = a + 1;
PRE-incremenatare: x = ++a;
a = a + 1;
x = a;
Operatori la nivel de bit
Avem şase operatori la nivel de bit,aceștia se aplică tipurilor char,int,long signed/unsigned,iar rezultatul este un întreg. Operatorii la nivel de bit sunt următorii.
~
- negare la nivel de bit&
- AND (şi logic)|
- OR (sau logic)^
- XOR (sau exclusiv)<<
- deplasare la stânga>>
- deplasare la dreapta
Operator de negare be biți (BWNOT)
Operatorul de negare realizează complementarea biților, biții de 0 se pun 1, iar biții de 1 se pun 0.
int a = 2200; /* 0....0 1000 1001 1000*/
a = ~a; /* 1....1 0110 0110 0111*/
Operatorul ȘI pe biți (BWAND)
Dorim să aflăm valoarea bitului de pe poziția 2 a numarului 20.Pentru a afla valorea acestui bit se poate realiza operația AND (&) între numărul dorit și un alt număr binar care are doar pe poziția dorită valoarea 1 (în cazul nostru poziția 2),astfel dacă rezultatul este diferit de 0 atunci inițial am avut bitul 1, respectiv 0 dacă bitul a fost 0.
A | B | A AND B |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
#include <stdio.h>
int main() {
int a = 20; /* 0...0 1 0 1 0 0 */
int b = 4; /* 0...0 0 0 1 0 0 */
if (a & b) {/* 0...0 0 0 1 0 0 */
printf("Rezultatul este diferit de 0\n");
} else {
printf("Rezultatul are valoarea 0\n");
}
return 0;
}
Operatorul SAU pe biți (BWOR)
Dorim să setăm (în 1) valoarea bitului de pe poziția 2 a numarului 20. Pentru a seta valorea acestui bit se poate realiza operația OR (|) între numărul dorit și un alt număr binar care are doar pe poziția dorită valoarea 1 (în cazul nostru poziția 2).
A | B | A OR B |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
int main() {
int a = 20; /* 0...0 1 0 1 0 0 */
int b = 4; /* 0...0 0 0 1 0 0 */
int c = a | b; /* 0...0 1 0 1 0 0*/
return 0;
}
Operatorul SAU EXCLUSIV pe biți (BWXOR)
Dorim să schimbăm valoarea bitului de pe poziția 2 a numarului 20. Pentru a schimba valorea acestui bit se poate realiza operația XOR (^) între numărul dorit și un alt număr binar care are doar pe poziția dorită valoarea 1 (în cazul nostru poziția 2).
A | B | A XOR B |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
int main() {
int a = 20; /* 0...0 1 0 1 0 0 */
int b = 4; /* 0...0 0 0 1 0 0 */
int c = a ^ b; /* 0...0 1 0 0 0 0*/
return 0;
}
Operatorul de deplasare la stânga
Operatorii de deplasare (<< şi >>) realizează deplasarea biţilor din operandul stâng cu atâtea poziţii câte sunt indicate de operandul drept.
int a = 255; /* 0...0 0000 1111 1111*/
a = a << 3; /* 0...0 0111 1111 1000*/
Exerciții
- Scrieți un program care să citească un număr în virgulă mobilă de la tastatură și să se afișeze, pe linii diferite, în hexazecimal, semnul, mantisa și exponentul. Notă: pentru a putea efectua operații pe biți, operanzii trebuie să fie de tip întreg. Astfel, pentru a interpreta un număr în virgulă mobilă ca secvență de biți, variabila trebuie sa fie de tip int, iar citirea să se facă cu template-ul "%f".
- Scrieți un program care să citească de la tastatură un număr întreg fără semn pe 8 biți (în bază 10) și să-l afișeze pe ecran în baza doi, folosind operatori de shiftare și mascare.
- Citiți de la tastatură un număr întreg cu semn, pe 32 de biți, apoi negați-l aritmetic și afișați valoarea, fără să folosiți operatorului unar "-" (folosind regulile convenției complement față de 2).
- Scrieți un program care să citească un număr întreg pozitiv pe 8 biți de la tastatură, să numere și să afișeze câți biți de 1 și câți biți 0 are reprezentarea lui binară.
- Citiți de la tastatură un număr întreg n, calculați și afișați suma numerelor de la 0 la n.
- Citiți o valoare de temperatură în grade Celsius, și afișați pe ecran valoarea acelei temperaturi în Kelvin și grade Fahrenheit.
- Fie o matrice de 8 linii și 10 coloane, cu elementele numerotate de la 0 (elementul din stânga sus) la 79 (elementul din dreapta jos):
Dându-se de la tastatură un index n între 0 si 79, să se afișeze pe ce linie și pe ce coloană este indexul respectiv.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 70 71 72 73 74 75 76 77 78 79
- Dându-se un număr întreg de la tastatură, să se afișeze 0 dacă numărul este impar și 1 dacă este par.
- Dându-se un număr întreg de la tastatură, să se afișeze restul împărțirii numărului la 16, folosind doar operații pe biți.
dificil
Folosind doar operații pe biți (fără construcții condiționale), să se calculeze modulul unui număr întreg pe 32 de biți, introdus de la tastatură.