Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

9
Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

description

Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu. Agenda. Includerea fişierelor Macrodefiniţii şi substituţii Compilare condiţionată. Preprocesarea. - PowerPoint PPT Presentation

Transcript of Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Page 1: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Programare in limbajul C – Cursul 10Preprocesorul C

Prof. univ. dr. Constantin Popescu

Page 2: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Agenda Includerea fişierelor Macrodefiniţii şi substituţii Compilare condiţionată

Page 3: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Preprocesarea Preprocesarea este o fază de traducere a codului sursă

care este aplicată înainte de compilare. Preprocesorul execută substituţii de text în codul sursă în trei moduri:– Includerea fişierelor: introducerea conţinutului unui alt fişier

în fişierul sursă, ca şi cum l-am fi scris în acel fişier.– Macrosubstituţii: înlocuirea unei secvenţe de text cu alta.– Compilare condiţionată: în funcţie de unele circumstanţe,

unele părţi ale codului sursă sunt (sau nu sunt) luate în considerare de compilator.

În primul rând, comenzile pentru preprocesor se scriu pe o singură linie. Preprocesorul nu cunoaşte sintaxa limbajului C - funcţii, instrucţiuni sau expresii.

Cu ajutorul preprocesorului putem cu foarte multă uşurinţă să transformăm un text sursă care nu seamănă cu un program C într-un program C.

Page 4: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Includerea fişierelor O linie de forma

#include <numefisier.h> sau

#include "numefisier.h" va determina citirea conţinutului fişierului numefiser.h,

adăugarea lui în fişierul curent şi compilarea acelui conţinut la un moment dat.

De exemplu, presupunem că nu mai vrem să scriem de fiecare dată la începutul fiecărui fişier sursă, prototipurile funcţiilor externe cum este:

extern int getline(char [], int); Am putea plasa prototipul într-un fişier header, care poate avea

numele getline.h, iar acest fişier poate fi inclus la începutul fiecărui fişier sursă care utilizează funcţia getline, folosind directiva:

#include "getline.h"

Page 5: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Macrodefiniţii şi substituţii (1) O linie pentru preprocesor de forma:

#define nume text defineşte un macro cu un nume dat, care are ca valoare textul

care este dat. După această definiţie, peste tot unde apare acel nume,

preprocesorul îl va înlocui cu textul de substituţie. O soluţie mult mai bună este folosirea macro-definiţiilor:

#define MAXLINE 100char line[MAXLINE];...getline(line, MAXLINE);

De exemplu, presupunem că scriem următoarele macro-uri:#define A 2#define B 3#define C A + B

Mai târziu putem scrie definiţia:int x = C * 2;

Page 6: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Macrodefiniţii şi substituţii (2) Dacă A, B şi C ar fi variabile obişnuite, atunci x ar lua val. 10. Preprocesorul întotdeauna substituie textul macroului exact aşa

cum a fost scris. Aşa că prima dată se va substitui textul pentru macro-ul C, rezultând:

int x = A + B * 2; După această substituţie vor fi înlocuite şi macro-urile A şi B ceea

ce va da:int x = 2 + 3 * 2;

Doar când preprocesorul a terminat de făcut toate substituţiile va intra în acţiune compilatorul. Când este evaluată expresia de mai sus, rezultatul va fi că x se iniţializează cu 8!

Pentru a evita astfel de probleme, este o idee bună să includem paranteze explicite în definiţiile macrourilor care conţin expresii. Dacă definim macroul C ca:

#define C (A + B) Atunci declaraţia lui x se va extinde la:

int x = (2 + 3) * 2; Ceea ce va iniţializa valoarea variabilei x la 10, aşa cum ne-am

propus iniţial.

Page 7: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Exemplu-Macrodefiniţii şi substituţii Program pentru contorizarea liniilor, cuvintelor şi caracterelor:#include <stdio.h>#define DA 1#define NU 0int main(){

int c,nl,nw,nc,inword;inword=NU;nl=nw=nc=0;

while((c=getchar())!=EOF){

++nc;if(c==’\n’)

++nl;if(c==’’||c==’\n’||c==’\t’)

inword=NU;else if(inword==NU){

inword=DA;++nw;

}}

printf("%d %d %d\n", nl,nw,nc);

return 0;}

Page 8: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Conversie din litera mica in litera mare#include <stdio.h>#include <ctype.h>

#define uppercase(x,n) for (i = 0; i < n; i++) x[i] = toupper(x[i])

int main (){

int i;char a[6] = {'h', 'e', 'l', 'l', 'o', '\0'};

printf ("a lowercase: %s\n", a);uppercase(a,6);printf ("a uppercase: %s\n",a);return 0;

}

Page 9: Programare in limbajul C – Cursul 10 Preprocesorul C Prof. univ. dr. Constantin Popescu

Compilare condiţionată-directiva #ifdef Dacă avem următoarea secvenţă:

#ifdef nume

textul programului

#else

textul programului

#endif Codul ce este compilat depinde de existenţa macroului nume. Dacă

acest macro este definit (adică am folosit linia #define nume), atunci se compilează textul programului cuprins între #ifdef şi #else iar textul dintre #else şi #endif este ignorat.

Dacă macroul nu este definit atunci se va compila textul sursă cuprins între #else şi #endif, textul cuprins între #ifdef şi #else fiind ignorat.

Aceasta seamănă cu o instrucţiune if, dar se comportă total diferit: o instrucţiune if controlează care instrucţiune se execută în momentul rulării programului, pe când #ifdef controlează care parte a programului este compilată.