programare 5

59
 CURS 12 PREPROCESAREA ÎN LIMBAJUL C/C++

Upload: alecsandra-rusu

Post on 04-Oct-2015

68 views

Category:

Documents


5 download

TRANSCRIPT

  • CURS 12

    PREPROCESAREA N

    LIMBAJUL C/C++

  • CUPRINS

    1. Noiuni introductive

    2. Includeri de fiiere

    3. Definiii de macro-uri

    4. Macrodefiniii cu parametri (funcii macro)

    5. Compilarea condiionat

    6. Alte directive preprocesor

    7. Macrouri predefinite

    8. Aseriuni

    9. Funcii inline

    2

  • 1. NOIUNI INTRODUCTIVE

    Preprocesorul (pp) execut operaii prealabile compilrii

    Pentru aceasta, fiierul iniial este transformat ntr-unul echivalent prin includeri de fiiere, macrodefiniii (macro-uri) i apeluri de macro-uri, compilare condiionat

    Directivele pp ncep cu simbolul # (diez) i au forma urmtoare:

    # nume_directiva simboluri

    un simbol este orice altceva dect un spaiu sau tab

    caracterul # trebuie s fie primul caracter ce nu este spaiu sau tab

    3

  • NOIUNI INTRODUCTIVE

    Intre caracterul # i directiv pot exista de asemenea spaii sau tab-uri:

    #define size 100

    # define size 100

    # define size 100

    Uzual, o directiv pp ocup o singur linie, dar este posibil ca directiva s continue pe mai multe linii folosind caracterul \ pe ultima poziie a liniei ce se continu

    Pe aceeai linie cu o directiv poate exista i un comentariu ce va fi ignorat de ctre pp

    De asemenea, dac un caracter # izolat apare pe o linie, va fi neglijat 4

  • 2. INCLUDERI DE FIIERE

    Se folosesc pentru a include fiiere antet:

    ce conin, de obicei, declaraii de constante, variabile i prototipuri de funcii

    Se fac cu directive #include

    nainte de compilare, se include n textul surs, n poziia curent, coninutul fiierelor antet specificate n directive

    Includerea este transparent utilizatorului

    5

  • INCLUDERI DE FIIERE

    Forme:

    #include

    #include "specificator_fisier

    Prima variant este folosit pentru a include fiiere antet ale mediului de programare, situate n anumite directoare specificate n setrile mediului

    A doua variant este folosit pentru a include fiiere antet proprii, situate n directorul curent sau n alt parte, caz n care se specific i calea

    6

  • INCLUDERI DE FIIERE

    Exemple:

    #include

    #include "my_decl.h" // cale relativa director curent

    #include "...\\file.h" // directorul parinte, SO Windows

    #include "D:/user/local/file.h" // cale completa, orice SO

    7

  • INCLUDERI DE FIIERE

    Includerea de fiiere poate fi imbricat:

    un fiier include un fiier antet care la rndul lui include alt fiier antet,

    Pot aprea conflicte dac exist identificatori cu acelai nume n fiierele incluse cu cei din fiierul curent

    8

  • 3. DEFINIII DE MACRO-URI

    Se fac cu directiva #define i respectiv #undef

    #define nume sir_caractere

    #undef nume

    Se folosesc pentru a defini constante simbolice sau mai general macrofuncii(dac apar i parametri), respectiv pentru a anula o definire anterioar

    Definirea este valabil din punctul n care apare directiva "#define" pn la ntlnirea unei directive "#undef" corespondente sau pn la sfritul fiierului

    9

  • DEFINIII DE MACRO-URI

    pp nlocuiete toate apariiile irului "nume" ce urmeaz liniei curente cu irul de caractere asociat n directiv, cu urmtoarele excepii:

    n interiorul unei constante caracter sau ir de caractere

    n interiorul comentariilor

    Inlocuirea se mai numete i expandare

    10

  • DEFINIII DE MACRO-URI

    De obicei se folosesc litere mari n "nume" pentru a recunoate mai uor n program constantele simbolice

    Intre "nume" i "sir_caractere" pot sa apar mai multe spaii albe (cel puin unul)

    Nu se folosete terminatorul ;

    dac acesta apare se consider c face parte din irul de substituie

    De cele mai multe ori constantele simbolice se folosesc pentru a asocia identificatori unor numere:

    ca urmare pot fi urmrite uor n program i pot fi uor modificate (ntr-un singur loc, prin modificarea irului de substituie)

    de reinut c nu se face declararea unei constante

    Dup o directiv #undef macro-ul poate fi redefinit

    11

  • DEFINIII DE MACRO-URI

    Exemple:

    #define DIM 100

    int tab[DIM];

    ...

    #undef DIM

    #define DIM 10

    #define CT_CAL 0.1234

    x = cit_CAD( ) * CT_CAL

    12

  • DEFINIII DE MACRO-URI

    Substituia se aplic i liniilor cu directive pp

    ca urmare un identificator definit ntr-o linie poate fi

    utilizat n alt directiv #define

    se recomand folosirea parantezelor pentru evitarea ambiguitilor ce pot conduce la efecte nedorite:

    #define MIN 1

    #define MAX MIN + 100

    ...

    rez = 10*MAX; // rez = 10*MIN + 100

    #define MAX (MIN + 100)

    rez = 10*MAX; // rez = 10*(MIN + 100) 13

  • DEFINIII DE MACRO-URI

    Dac irul de caractere (corpul macroului) este un ir vid atunci se obine tergerea identificatorului din codul surs

    O macrodefiniie nu va fi expandat n timpul propriei expandri, adic nu se ajunge la o expandare infinit:

    #define A A

    14

  • DEFINIII DE MACRO-URI

    Utilizarea constantelor simbolice este specific limbajului C, limbaj n care nu se pot defini constante

    In limbajul C++, prin folosirea modificatorului const, se

    pot folosi constante i se beneficiaz de verificrile de tip fcute de compilator

    15

  • DEFINIII DE MACRO-URI

    Exemple:

    C

    #define pi 3.14 - constant fr tip

    #define SIZE ROWS*COLS - valoare calculat prin substituie de pp unde ROWS si COLS au fost definite anterior

    #define SIZE 200 - eventual avertizare la redefinire

    C++

    const float pi = 3.14; - constant cu tip

    const int SIZE = ROWS*COLS; - valoare calculat de compilator prin evaluarea expresiei unde ROWS i COLS sunt definite in prealabil

    //const int SIZE = 200; - redefinire nepermis 16

  • 4. MACRODEFINIII CU PARAMETRI

    (FUNCII MACRO)

    Sintaxa:

    #define nume(p1, p2,...,pn) text

    unde:

    pi sunt parametri formali

    text este textul de substituie care va conine parametrii formali

    poate continua pe mai multe rnduri folosind

    caracterul '\ la sfritul fiecrui rnd

    17

  • MACRODEFINIII CU PARAMETRI

    Dac parametrii formali lipsesc avem o definiie de constant simbolic

    Intre "nume" i prima parantez "(" nu pot exista spaii albe (spatiu simplu, tab):

    dac apare acest spaiu, linia este interpretat ca o definire de constant simbolic al crei ir de substituie ncepe cu (

    Apelul unei macrodefiniii cu parametri se face analog apelului unei funcii:

    numele macro-ului urmat de parametrii efectivi ntre paranteze i separai prin virgule

    Parametrii efectivi se substituie parametrilor formali n textul de substituie, iar apoi textul rezultat se substituie apelului

    Reprezint primul mecanism generic introdus n limbajul C/C++

    18

  • MACRODEFINIII CU PARAMETRI

    Numrul parametrilor efectivi trebuie s coincid cu cel al parametrilor formali

    Corespondena dintre parametrii formali i cei efectivi se face prin poziie

    Pentru evitarea ambiguitilor se recomand folosirea parantezelor pentru fiecare parametru

    Anularea unei macrodefiniii cu parametri se face cu o directiv: #undef nume

    este posibil apoi redefinirea macro-ului

    19

  • MACRODEFINIII CU PARAMETRI

    Exemple:

    1. #define Sqr(a) (a)*(a)

    c = Sqr(a-b); // c = (a-b)*(a-b);

    #define Sqr(a) a*a

    c = Sqr(a-b); // c = a-b*a-b;

    2. #define abs(x) (x < 0 ? -x : x)

    a = abs(b-c); // a = (b-c < 0 ? b+c : b-c);

    #define abs(x) ((x) < 0 ? (-x) : (x))

    a = abs(b-c); // a = ((b-c) < 0 ? -(b-c) : (b-c))

    3. #define max2(a,b) (((a)>(b)) ? (a) : (b)) 20

  • MACRODEFINIII CU PARAMETRI

    Macrodefiniiile cu parametri se folosesc n cazul n care se folosesc calcule simple, eliminnd apelurile de funcii

    Operaii efectuate la apelul unei funcii: transferul parametrilor (de exemplu prin stiv) salvare adres de revenire salt la adresa de nceput a funciei

    Operaii ce se execut la revenirea dintr-o funcie: transferul rezultatului

    salt la adresa urmtoare apelului refacerea stivei (eliberarea stivei)

    21

  • MACRODEFINIII CU PARAMETRI

    Avantaje macrofunctiilor fa de funcii constau n faptul c se evit operaiile de la apelul/revenirea dintr-o funcie:

    n unele cazuri aceste operaii pot fi mai "costisitoare" dect calculul nsui

    Dezavantaje:

    creterea lungimii programelor datorit expandrii nu se fac verificri de tip la apel nu se aplic proprieti legate de domeniu de

    valabilitate

    nu se pot compila separat

    22

  • MACRODEFINIII CU PARAMETRI

    Alte considerente:

    -Macrofunciile n general nu returneaz o valoare i de aceea rezultatul este memorat de obicei n unul din parametrii ei

    -Putem avea situaii n care macrofuncia ofer un rezultat, mai ales la utilizarea operatorului condiional

    -Cuvintele cheie min, max sunt rezervate n unele medii de programare integrate i se genereaz erori la utilizarea lor ca i macro funcii

    23

  • EXEMPLE VARIANTA OPERATOR CONDITIONAL I IF

    A) #define MAX2(a,b) ((a)>(b)?(a):(b))

    Apel:

    cin >>a; cin >>b;

    cout>b;

    MAX2I(a,b);

    cout

  • 5. COMPILAREA CONDIIONAT

    Permite ca anumite zone din program s fie incluse sau excluse de la compilare

    Se folosete pentru:

    obinerea mai multor variante ale aceluiai program

    sau pentru creterea portabilitii programelor prin scrierea unui cod pentru anumite platforme hardware

    sau software

    25

  • COMPILAREA CONDIIONAT

    Directivele: #if, #else, #endif

    #if expr_ct

    sectiune_1

    [#else

    sectiune_2]

    #endif

    Exemplu:

    #define O_COND 2

    #if (O_COND != 0 && O_COND != 1)

    #error O_COND must be 0 or 1

    #endif 26

  • COMPILAREA CONDIIONAT

    Se poate genera o structur de selecie generalizat prin folosirea directivelor #elif :

    #if expr_ct1 [sectiune_1]

    [#elif expr_ct2 sectiune_2]

    ...

    [#elif expr_ctn sectiune_n]

    [#else sectiune_finala]

    #endif

    27

  • COMPILAREA CONDIIONAT

    Directivele #if se folosesc pentru omiterea temporar a unei zone de cod:

    de exemplu, n etapa de testare i depanare cnd se fac experimente pe zone de cod suspecte

    i cu ajutorul comentariilor pe mai multe linii se pot exclude zone de cod, ns aceste comentarii nu pot fi imbricate

    Dac expresia asociat unei directive #if are ntotdeauna valoarea zero, excluderea este asigurat:

    #if 0

    ...cod ce va fi exclus de la compilare

    #endif

    Altfel, pentru includere avem:

    #if 1

    ...cod ce va fi inclus la compilare

    #endif

    28

  • ALTE EXEMPLE

    #if !defined(NULL)

    #define NULL 0

    #endif

    -afisare la DEBUG a variabilei x:

    #ifdef DEBUG

    printf("Variable x = %d\n", x);

    #endif

    29

  • COMPILAREA CONDIIONAT

    Directivele: #ifdef, #ifndef

    #ifdef nume_m #ifndef nume_m

    sectiune_1 sectiune_1

    [#else [#else

    sectiune_2] sectiune_2]

    #endif #endif

    n aceste construcii nu se pot folosi directive #elif

    30

  • COMPILAREA CONDIIONAT

    Operatorul defined: defined(nume_macro)

    Are valoarea 1 dac numele a fost definit anterior cu directiva #define i definiia nu a fost anulat cu directiva #undef

    Poate fi folosit doar n expresiile asociate directivelor #if i #elif, dar pot fi combinai folosind operatori logici (negaie, and, or)

    #ifndef NULL

    #if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)

    #define NULL 0

    #else

    #define NULL 0L

    #endif

    #endif

    31

  • COMPILAREA CONDIIONAT

    Compilarea condiionat poate fi folosit i pentru a evita includerea multipl a fiierelor antet

    n cazul unui fiier antet cu numele file.h se vor folosi urmtoarele directive pp:

    #ifndef _FILE_H_

    #define _FILE_H_

    definire continut fisier file.h

    #endif

    32

  • EXEMPLU- HEADER BOOLEAN.H

    #ifndef BOOLEAN_H

    typedef int boolean; // means literal string 'int' is same as 'boolean'

    const boolean FALSE = 0;

    const boolean TRUE =1;

    #define BOOLEAN_H

    #endif

    33

  • #define Module10

    #define MyVersion 1.1

    #include

    using namespace std;

    #include "boolean.h"

    #include

    int main(void){

    cout

  • #ifndef MyVersion

    cout

  • // program using the user defined header file, boolean.h

    cout

  • 37

  • 6. ALTE DIRECTIVE PREPROCESOR

    #pragma nume_directiva

    Permite utilizarea unor directive specifice implementrii Dac directiva specificat nu este recunoscut nu se

    genereaz eroare i se trece mai departe Directiva este folosit de furnizorii de compilatoare

    pentru a introduce faciliti nestandard ale pp, specifice acelei implementri

    Exemplu:

    #pragma warn-aus

    void LinkFloat (void){

    float f=0; *pf=&f;}

    #pragma warn-aus

    38

  • ALTE DIRECTIVE PREPROCESOR

    #pragma inline

    specific faptul c n modulul curent apar instruciuni n limbaj de asamblare

    #pragma startup nume-functie

    #pragma exit nume-functie

    Aceste directive pp permit specificarea unor funcii ce vor fi apelate naintea nceperii execuiei programului (nainte de apelul funciei main()), respectiv nainte de terminarea execuiei programului

    Funciile specificate trebuie s aib urmtorul prototip: void func(void);

    39

  • Cuvntul cheie pragma este parte din limbajul C++

    standard, dar forma, coninutul i sensul lui pragma este diferit pentru fiecare compilator.

    Aceasta nseamn c diferite compilatoare vor avea diferite directive pragma.

    Diversele forme pragma nu sunt definite de standardul

    C++. Codul care depinde de pragma nu este portabil. n

    mod normal este utilizat in procesul de debugging.

    Pentru alte directive #pragma, verificai documentatia compilatoarelor i, de asemenea, standardul ISO/IEC C/C++ pentru orice actualizri.

    40

  • 7. MACROURI PREDEFINITE

    __cplusplus , definit ca 1 dac este vorba de un modul C++ i este nedefinit n caz contrar

    _LINE_, este un macro care contine o valoare intreaga,

    care reprezinta numarul liniei din fisierul sursa supusa

    compilarii.

    _DATE_, este un macro care contine un sir de caractere ce

    reprezinta data curenta a sistemului in forma: luna/zi/an

    _FILE_, este un macro care contine un sir de caractere ce

    reprezinta numele fisierului supus compilarii

    _TIME_, este un macro care contine un sir de caractere ce

    reprezinta timpul la care a inceput compilarea sub forma:

    ore:minute:secunde 41

  • __STDC__ : are valoarea 1 dac compilatorul se

    aliniaz standardului ANSI

    Nu pot fi anulate cu directiva #undef Se pot utiliza n programe la fel ca orice ali

    identificatori

    Exemplu:

    #include

    #include

    void main(void){

    printf(Se compileaza %s, linia= %d, data= %s timpul= %s, _FILE_, _LINE_, _DATE_, _TIME_);

    _getch();

    }//main

    42

  • OPERATORUL # - transform argumentul unei funcii macro ntr-un ir ntre ghilimele

    #include

    #define MAKESTR(str) #str

    void main(void)

    {

    int valoare=100;

    printf( %s is %d, MAKESTR(valoare), valoare);

    }

    Programul va afisa:

    valoare is 100

    43

  • OPERATORUL ## - concateneaz doi identificatori

    #include

    #define output(l) printf(%d %d\n,l##1, l##2)

    void main(void){

    int count1, count2;

    int l1, l2;

    count1=10;

    count2=64;

    l1=100;

    l2=82;

    output(count); //Afiseaza 10 si 64

    output(l);//Afiseaza 100 si 82}

    44

  • #include

    #include

    #define HELLO(x) printf("Hello, " #x "\n");

    #define SHOWFUNC(x) Use ## Func ## x

    int main(void)

    {

    // new concatenated identifier, UseFuncOne

    char * SHOWFUNC(One);

    // new concatenated identifier, UseFuncTwo

    char * SHOWFUNC(Two);

    SHOWFUNC(One) = "New name, UseFuncOne";

    SHOWFUNC(Two) = "New name, UseFuncTwo";

    HELLO(Birch);

    printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(One));

    printf("SHOWFUNC(Two) -> %s \n",SHOWFUNC(Two));

    _getch();

    return 0;

    }

    45

  • 46

  • 8. ASERIUNI

    Aceasta este o macrodefiniie folosit la gestiunea excepiilor dintr-un program C++.

    Macrofuncia assert(), e definit n fiierul antet assert.h, i testeaz valoarea unei expresii date ca parametru.

    Dac valoarea expresiei este 0 (false), atunci assert() afieaz un mesaj de eroare i apeleaz funcia abort() (din biblioteca stdlib.h) pentru a termina execuia programului.

    Acest mecanism e util n procesul de debugging, de

    exemplu pentru a testa dac o variabil are o valoare corect sau nu.

    47

  • Ca exemplu, presupunem c variabila q nu poate avea niciodat o valoare mai mare dect 100 n program.

    O aseriune poate fi folosit pentru a testa valoarea lui q i a afia un mesaj de eroare dac valoarea lui q e incorect.

    Poate fi folosit urmtoarea construcie :

    assert(q

  • EXEMPLU ASSERT #include

    #include

    #include

    #include

    #include

    void TestString(char *string);

    void main()

    {

    // first test array of char, 10 characters...

    // should be OK for the 3 test conditions...

    char test1[ ] = "abcdefghij";

    // second test pointer to string, 9 characters...

    // should be OK for the 3 test conditions...

    char *test2 = "123456789";

    // third test array char, empty...

    // should fail on the 3rd condition, cannot be empty...

    char test3[ ] = "";

    49

  • printf("Testing the string #1 \"%s\"\n", test1);

    TestString(test1);

    printf("Testing the string #2 \"%s\"\n", test2);

    TestString(test2);

    printf("Testing the string #3 \"%s\"\n", test3);

    TestString(test3);

    _getch();

    }//main

    void TestString(char * string)

    {

    // set the test conditions...

    // string must more than 8 characters...

    assert(strlen(string) > 8);

    // string cannot be NULL

    assert(string != NULL);

    // string cannot be empty....

    // test3 should fail here and program abort...

    assert(string != '\0');

    } 50

  • 51

  • 9. FUNCII INLINE

    inline val_ret nume_func(list_param_formali);

    Sunt specifice limbajului C++

    S-au introdus pentru a elimina neajunsurile

    macrodefiniiilor cu parametri legate de verificrile de tip la apel

    Se definesc ca i celelalte funcii, n plus se adaug cuvntul cheie inline

    52

  • FUNCII INLINE

    Funciile inline pstreaz proprietile funciilor legate de:

    verificrile de la apel (numr i tip pentru parametri)

    modul de transfer al parametrilor

    domeniul declaraiilor locale i al parametrilor

    i pentru aceste funcii are loc o substituie (inserare - expandare) de text, dar nu de ctre pp ci de ctre compilator

    compilatorul poate s nu poat efectua o asemenea operaie, caz n care se genereaz o funcie obinuit

    53

  • FUNCII INLINE

    Restricii:

    funcia trebuie s fie simpl (cteva instruciuni 2-3)

    s nu conin instruciuni ciclice (do-while, for, while) nu obligatoriu

    s fie definit i utilizat n acelai modul

    nu pot fi compilate separat

    nu se pot utiliza pointeri ctre aceste funcii

    54

  • FUNCII INLINE

    Exemple:

    inline char comp(int a, int b)

    {

    if(ab) return('>');

    return('=');

    }

    inline int max(int a, int b)

    {

    return ((a>b) ? a : b);

    } 55

  • FUNCII INLINE

    Comparaie ntre funcii inline i macrodefiniii cu parametri:

    #define square(x) ((x)*(x))

    cout

  • FUNCII INLINE

    Funcia inline echivalent:

    inline int square(int x)

    {

    return x*x;

    }

    In acest caz avem un apel obinuit de funcie:

    cout

  • n cazul definirii unei funcii macro MAX:

    #define MAX (l, j) ((l) > (j) ? (l ): (j))

    putem apela macro-ul MAX astfel:

    int a, b, c;

    c = MAX (a*b, a+b); //care se va expanda in

    //c = ((a*b) > (a+b) ? (a*b) : (a+b));

    58

  • i n acest caz o funcie inline care ar realiza acelai lucru ar fi:

    inline int mmax(int x, int y)

    {

    return (x) >(y) ? (x ): (y);

    }

    i apelul ei se face cu:

    c = mmax(a*b, a+b);

    astfel nct la compilare funcia mmax se va expanda ca i o funcie macro.

    59