Documente Academic
Documente Profesional
Documente Cultură
2018
3 21:40 4
Tipul bool
for ( int i = 2; i < n/2; ++i)
if ( n % i == 0 )
return false;
#include <stdio.h> return true;
• Tipul de date logic în C99 este _Bool, care poate avea #include <stdbool.h> }
doar valorile 0 sau 1. bool ePrim( int );
int main( void ) {
• Atribuind orice valoare nenulă unui _Bool el devine 1. for ( int i = 1; i <= 2; ++i ) {
int numar;
printf( "Numar = " ); scanf( "%d", &numar );
• C99 furnizează fișierul header <stdbool.h> care
bool numarPrim = ePrim( numar );
definește macrouri reprezentând tipul de date bool și if ( numarPrim )
valorile sale: true și false. printf( "%d este prim \n\n", numar );
else
printf( "%d nu este prim \n\n", numar );
• Aceste macrouri înlocuiesc true cu 1, false cu 0 și }
bool cu cuvântul cheie _Bool. }
21:40 PCLP CURS 12 5 21:40 PCLP CURS 12 6
Curs PCLP 12 1
05.09.2018
Numere complexe
• Standardul C99 introduce suport pentru numere
complexe și aritmetica lor prin includerea fișierului
header <complex.h>
• Macroul complex este expandat la cuvântul
cheie _Complex:
tip de date ce alocă un tablou de exact două
NUMERE COMPLEXE elemente, corespunzând
HEADERUL <complex.h> părții reale și părții imaginare a unui număr
complex,
o pereche de numere reale în virgulă mobilă.
21:40 7 21:40 PCLP CURS 12 8
Numere complexe
#include <stdio.h>
#include <complex.h>
int main(void){
Formă număr complex
• Sufixele f și l desemnează tipul float complex
double complex z1 = 1.5 + 1.7*I, z2 = 1.5 - 1.7*I; sau long double complex.
printf( "forma algebrica a numarului complex:
%g%+gi\n", creal(z1), cimag(z1) ); • Macrourile I și _Complex_I reprezintă
printf( "forma trigonometrica: modulul = %g argumentul
= %g\n", cabs(z1), carg(z1) ); Specificator de format numărul complex (0, 1) notat în matematică cu i.
printf( "complex conjugatul: %g%+gi\n\n",
creal(conj(z1)), cimag(conj(z1)) ); În cazul în care se dorește utilizarea identificatorului
printf( "forma algebrica a numarului complex: %g%+gi\n", I în alt scop se poate invalida macroul I.
creal(z2), cimag(z2) ); #include <complex.h>
printf( "forma trigonometrica: modulul = %g argumentul = #undef I
%g\n", cabs(z2), carg(z2) );
printf( "complex conjugatul: %g%+gi\n\n", creal(conj(z2)), Putem defini o altă prescurtare pentru _Complex_I,
cimag(conj(z2)) );
} de exemplu J.
21:40 PCLP CURS 12 11 21:40 PCLP CURS 12 12
Curs PCLP 12 2
05.09.2018
Adunare numere
+
#include <stdio.h>
complexe
- Scădere
Numere complexe
#include <complex.h> * Înmulțire
#include <stdio.h>
#include <complex.h>
int main(void){
long double complex z1 = 1.5l + 1.7l*I, z2 = 0l - 0l*I;
printf("z1 = %.1f%+.1fi\n\n", creal(z1), cimag(z1));
printf("z1++ = %.1f%+.1fi\n\n", creal(z1++), cimag(z1++));
z1 = 1.5l + 1.7l*I;
printf("z1-- = %.1f%+.1fi\n\n", creal(z1--), cimag(z1--));
printf("z2 = %.1f%+.1fi\n\n", creal(z2), cimag(z2));
printf("!z1: %.1f%+.1fi\n\n", creal(!z1), cimag(!z1));
printf("!z2: %.1f%+.1fi\n\n", creal(!z2), cimag(!z2));
printf("z1 == z2: %.1f%+.1fi\n\n",
creal(z1==z2), cimag(z1==z2));
printf("z1 != z2: %.1f%+.1fi\n\n",
creal(z1!=z2), cimag(z1!=z2));
TABLOURI DE LUNGIME VARIABILĂ
printf("z1 && z2: %.1f%+.1fi\n\n",
creal(z1&&z2), cimag(z1&&z2));
printf("z1 || z2: %.1f%+.1fi\n\n",
creal(z1||z2), cimag(z1||z2));
}
21:40 PCLP CURS 12 15 21:40 16
Curs PCLP 12 3
05.09.2018
Curs PCLP 12 4
05.09.2018
struct student
#include <stdio.h>
#include <stdbool.h>
{
char nume[10];
Aplicație cu figuri geometrice
#include <string.h> union { // union anonim
int main(){
bool integralist; • Reluăm o aplicație din Laboratorul 10 (despre
int numarRestante;
struct student s; }; typedef, union, bitfields) care, într-un vector de
}; struct figuri geometrice, citea:
strcpy(s.nume, "Ionescu");
s.integralist = false; //accesare directa a membrilor union tipul figurii geometrice și apoi
s.numarRestante = 2; //accesare directa a membrilor union
printf("Nume student = %s, are %d restante\n", s.nume, dacă tipul era cerc, citea valoarea razei,
s.numarRestante); dacă tipul era triunghi citea cele valorile celor trei laturi,
strcpy(s.nume, "Popescu"); dacă tipul era dreptunghi citea valorile celor două laturi.
s.integralist = true; //accesare directa a membrilor union
printf("Nume student = %s, %s\n", s.nume, • Vom simplifica struct figuri folosind facilitatea
s.integralist?"integralist":"restantier");
} de struct și union anonime imbricate, astfel:
21:40 PCLP CURS 12 25 21:40 PCLP CURS 12 26
Curs PCLP 12 5
05.09.2018
Curs PCLP 12 6
05.09.2018
Curs PCLP 12 7
05.09.2018
Curs PCLP 12 8
05.09.2018
definește câteva macro-uri cu tip generic (_Generic). • Dacă x este un long double, sin(x) va apela
sinl (versiunea pentru long double a lui sin)
• Odată inclus header-ul <tgmath.h>, macro-urile
cu tip generic vor apela funcții corespunzătoare • Dacă x este un număr complex, sin(x) va apela
tipului argumentelor. versiunea corespunzătoarea funcției sin pentru tipul
complex (csin, csinf sau csinl).
• Dacă x este un float, expresia sin(x) va apela
sinf (versiunea pentru tipul float a lui sin). double complex float complex long double complex
Curs PCLP 12 9
05.09.2018
Curs PCLP 12 10
05.09.2018
#include <stdio.h>
printf("double: sin(%g) = %g\n\n", d, msin(d));
#include <tgmath.h>
#include <complex.h>
printf("long double: sin(%.5lf) = %.20lf\n\n", ld,
#define msin(X) _Generic( (X), long double: sinl, msin(ld));
default: sin, double complex: csin, float complex:
printf("double complex: sin(%g%+gi) = %g%+gi\n\n",
csinf, long double complex: csinl)(X)
creal(dc), cimag(dc), creal(msin(dc)), cimag(msin(dc)) );
int main()
printf("float complex: sin(%g%+gi) = %g%+gi\n\n",
{
creal(fc), cimag(fc), creal(msin(fc)), cimag(msin(fc)));
double d = 0.12595;
long double ld = 0.12595; printf("long double complex:sin(%.5lf%+.1lfi) =
double complex dc = 0.12595 + 0.1*I; %.20lf%+.10lfi\n\n", creal(ldc), cimag(ldc),
float complex fc = 0.12595f + 0.1f*I; creal(msin(ldc)), cimag(msin(ldc)));
long double complex ldc = 0.12595l + 0.1l*I; }
21:40 PCLP CURS 12 61 21:40 PCLP CURS 12 62
FUNCȚII inline
Curs PCLP 12 11
05.09.2018
static inline char majuscula(char litera) { extern inline char majuscula(char litera) {
return ((litera >= 'a' && litera <= 'z') ? litera return ((litera >= 'a' && litera <= 'z') ? litera
- ('a' - 'A') : litera ); - ('a' - 'A') : litera );
} }
int main() {
int tmp, x = 3, y = 7;
Curs PCLP 12 12
05.09.2018
Curs PCLP 12 13
05.09.2018
Multithreading
• Pentru un programator obișnuit în C, cea mai mare
schimbare adusă de C11 este
suportul standardizat multithreading.
Multithreading Multithreading
• Inițial au apărut procesoare multicore de tip dual • Pentru a profita la maxim de avantajele
core, arhitecturii multicore
dar la ora actuală sunt extrem de răspândite trebuie să fim capabili să scriem aplicații multifir.
procesoare quad core sau octa core
și numărul de nuclee continuă să crească.
• Când un program împarte task-urile în fire
(threads) distincte,
• În sistemele multicore, fiecare nucleu poate un sistem multicore poate rula aceste fire în
procesa diferite părți ale aplicațiilor paralel.
și astfel aplicațiile și programele se termină mai
repede.
21:40 PCLP CURS 12 81 21:40 PCLP CURS 12 82
Multithreading Multithreading
• Headerul <threads.h> permite scrierea de cod • Executarea unei aplicații multifir pe un procesor cu
C multifir mult mai portabil decât în standardele C un singur nucleu
anterioare. poate conduce la un timp mai mare decât simpla
rulare secvențială a firelor.
• Simpla divizare a unui task în două fire și rularea
lor separată pe un sistem cu două nuclee nu va • În continuare prezentăm două programe:
duce la dublarea vitezei de execuție, cu toate că
1. Unul care rulează secvențial două sarcini cu efort
viteza va fi mai mare decât la rularea secvențială a de calcul mare.
firelor task-ului.
2. Altul care rulează aceleași sarcini pe fire de
execuție paralele.
21:40 PCLP CURS 12 83 21:40 PCLP CURS 12 84
Curs PCLP 12 14
05.09.2018
Multithreading
• Vom executa fiecare program pe un computer dual
core cu Windows 7.
• Vom măsura timpul pentru fiecare calcul si timpul
total de calcul pentru ambele programe.
• Ieșirile programelor arată îmbunătățirea timpilor
de rulare când programele multifir se execută pe
sisteme multicore.
Curs PCLP 12 15
05.09.2018
2. Execuția paralelă pe mai multe fire a 2. Execuția paralelă pe mai multe fire a
unor sarcini cu efort de calcul mare unor sarcini cu efort de calcul mare
• Programul următor utilizează tot o funcție Fibonacci • Deși timpul total de execuție poate varia de la o
recursivă, rulare la alta,
dar execută fiecare apel al funcției Fibonacci în fire timpul total de execuție în fire separate este
separate. totdeauna mai mic decât cel al programului cu
calcul secvențial al termenilor Fibonacci.
• Programul permite rularea pe sisteme multicore
(dual core, quad core sau octo core)
putând permite și sisteme cu mai multe nuclee
prin modificarea constantei MAX_FIRE definită la
începutul programului.
21:40 PCLP CURS 12 95 21:40 PCLP CURS 12 96
Curs PCLP 12 16
05.09.2018
// fiecare fir are nevoie de un identificator de fir de tipul // astept terminarea fiecarui calcul
// thrd_t pastram acesti identificatori intr-un tablou cu
for (int i = 0; i < numarFire; ++i)
// index numarul firului
thrd_join(numeFir[i], NULL);
thrd_t numeFir[numarFire];
// in acest punct calculele s-au terminat, firele s-au executat
for(int i = n; i > n - numarFire; --i) // trebuie sa calculam momentul cand s-a declansat executia
printf("fib(%d) ", i); // primului fir si momentul cand ultimul fir si-a incheiat
printf("in fire separate\n\n"); // executia pentru ca prin diferenta lor sa determinam timpul
// total de calcul pentru toate firele
// creare si lansare fir
// determinarea momentului cand a inceput primul fir
for(int i = 0; i < numarFire; ++i) { time_t timpStart = dateFire[0].timpStart;
printf("Start fir de calcul fibonacci(%d)\n", for(int i = 1; i < numarFire; ++i)
dateFire[i].termen); if(dateFire[i].timpStart < timpStart)
if(thrd_create(&numeFir[i], lansareFib, timpStart = dateFire[i].timpStart;
&dateFire[i]) != thrd_success)
printf("Esec creare fir" );
}
21:40 PCLP CURS 12 101 21:40 PCLP CURS 12 102
Curs PCLP 12 17
05.09.2018
// determinarea momentului cand s-a terminat ultimul fir // functie apelata de fiecare fir pt lansare calcul termen Fibo
creează un identificator al firului și îl stochează • Creează toate cele numarFire fire prin apelul
într-un obiect thrd_t. funcției thrd_create.
• Identificatorul firului poate fi ulterior utilizat cu • Cele trei argumente ale funcției sunt:
diferite funcții multifir. 1. Un pointer la thrd_t pe care thrd_create îl
utilizează pentru a stoca identificatorul firului.
21:40 PCLP CURS 12 107 21:40 PCLP CURS 12 108
Curs PCLP 12 18
05.09.2018
Curs PCLP 12 19
05.09.2018
BIBLIOGRAFIE
[1] Deitel, P., Deitel, H., C - How to program, 8th ed., Pearson
Publisher, 2016.
[3] Klemens, B., 21st Century C, 2nd ed., O’Reilly Media Inc., USA,
2015.
Curs PCLP 12 20