MACROCOMENZI

abbr. MCA

MCA poate fi considerata o generalizare a conceptului de constanta, in sensul ca referirea la o macrocomanda este inlocuita la compilare cu corpul macrocomenzii; MCA se expandeaza la compilare intr-o secventa de cod descrisa in corpul MCA. MCA reprezinta un suport foarte puternic pt programarea generica in C.

Build:

  • precompilare

  • compilare

  • link editare

Inainte de a se trece la compilare pot exista cateva prelucrari initiale ale codului sursa. Aceste prelucrari sunt specificate de catre programator folosind #.

  • #include : intregi fisiere sunt introduse in locul in care apare includerea (fisiere antet);

  • #define : macrocomenzi;

  • precompilare conditionata: #ifdef, #if, etc.

O MCA se specifica cu #define, denumirea macrocomenzii si eventual specificatia expandarii macrocomenzii.

1#define  ROAD

Dupa denumirea MCA poate sa apara un text care arata modul in care o MCA se expandeaza in cod C.

1#define PI 3.14159

De fiecare data cand in codul sursa apare cuvantul PI, in etapa de precompilare fiecare aparitie va fi inlocuita cu valoarea din definitie, adica 3.14159.

ex. .. code-block:: c

linenos

int x = PI; //—>precompilare int x = 3.14159;

O MCA poate avea parametri; expandarea MCA facandu-se in functie de acesti parametri.

ex

1#define suma(x,y) x+y
2int n = suma(1,2); //in etapa de precompilare ---> int n = 1+2;
3int expresie = suma(1+2)*2 //in etapa de precompilare ---> int expresie = (1+2)*2; ---> int expresie = 5;

ex

1#define suma(x,y) (x+y)
2int p = suma(1,2)*2 //---> int p = (1+2)*2; ---> int p = 6;

ex.

1#define prod(x,y) ((x)*(y))
2int x = prod(1+2,3+4); //---> int x = (1+2)*(3+4); ---> int x = 3*7; ---> int x = 21;

ex.

1#define max(x,y) (x>y)?(x):(y)
2int m = max(max(1+2,3+4),5+6);

ex.

1#define inter(x,y) x=x+y,y=x-y,x=x-y
2int a = 1, b = 2;
3inter(a,b); //---> a=a+b,b=a-b,a=a-b;

Operatorul ,

In limbajul C, virgula , este operator binar

1a,b //are valoarea returnata de catre operatorul virgula egala cu valoarea lui b
2int x = 1,2; //x = 2
3int y = ++x,x*2,x+5; // ++x este 3, x*2 este 6, x+5 este 8, deci y = 8
4y = ++x,(x*=2),x+5.9; // double > int     ++x este 4, (x*=2) este 8, x+5.9 este 13.9

Operatorul =

In limbajul C, egal = este operatoru binar in care in stanga este o variabila, iar in dreapta o expresie.

1a=b //valoarea lui b este convertita si atribuita variabilei a (conversie la tipul variabilei a)
2//valoarea returnata de = este cea atribuita lui a
3int x = 1;
4int y = x = 2;
5float u = 1.7f;
6int n = u = 5.9f; //u=5.9 si n=5
7// 1.5 constanta de tip double pe 8 octeti
8// 1.5f constanta de tip float pe 4 octeti

O MCA se poate scrie numar pe o singura linie

ex.

1#define inter2(x,y,z) z=x;\
2                      x=y;\
3                      y=z;
4//punand backslash \ compilatorul intelege ca linia curenta continua dedesubt
5
6int a = 1, b = 2, inte;
7inter2(a,b,inte)
8//nu este necesar a se pune ; dupa o macrocomanda
9//---> inte = a ; a = b ; b = inte ;

ex.

1#define inter3(x,y){\
2                    int inte = x;\
3                    x = z;\
4                    y = inte;\
5                    }
6inter3(a,b)
7//---> {int inte = a ; a = b ; b = inte ;}

Operatorul ##

poate fi folosit in cadrul unei MCA

prin a##b intelegem ca textul a este lipit de textulb, deci ab.

ex

1#define alip(a,b) a##b
2int intersch = 7;
3alip(inter,sch)++; //---> intersch++; ---> intersch = 8;
4int x = alip(12,3); //---> x = 123
5int y = alip(x+,2); //---> y = x + 2; ---> y = 125;
6int f = 4;
7float u = alip(1+2,0.1f); //---> 1 + 20.1f

ex

1#define max2(x,y,z) if(x<y)\
2                    z=x;\
3                    else\
4                    z=y;
5int a = 1, b = 2, c;
6max2(a,b,c);

Macrocomenzi standard

__FILE__: se expandeaza intr-un script continand numele fisierului curent la care s-a ajuns cu compilarea. ex. fisierul: test.c

1#include "stdio.h"
2void main(){
3    printf(__FILE__); // printf(".../test.c");
4}

__LINE__ : se expandeaza intr-un nr intreg reprezentand indicele liniei pe care apare macrocomanda __LINE__ ex.

1#include "stdio.h"
2void main(){
3    printf("%s:%d\n",__FILE__,__LINE__); // printf(".../test.c:4");
4}

__TIME__ : se exandeaza intr-un string ce contine ora la care s-a trecut prin precompilare

__DATE__ : se exandeaza intr-un string ce contine data la care s-a trecut prin precompilare

1printf("Eroare: impartire prin 0. Fisier: %s, linia: %d, data si ora compilarii %s %s\n", __FILE__, __LINE__, __DATE__, __TIME__);
2//pe baza acestor informatii putem gasi versiunea exacta a erorii

MCA __FILE__, __LINE__, __TIME__, __DATE__ sunt folosite la depanare. Aceste mesaje se conecteaza de obicei intr-un fisier LOG (log file). Un fisier LOG colecteaza mesaje de-a lungul executiei aplicatiei: valori, atentionari, erori, informatii, etc.

__STDC__ :se expandeaza in 1 sau 0 dupa cum compilatorul respecta sau nu standardul ISO

``__STDC_VERSION__ se expandeaza intr-un nr intreg de tip long si acesta reprezinta versiunea standard de compilare (pt ce versiune de C a fost implentat) in formatul YYYYMM

__cplusplus: se expandeaza in 1 daca si numai daca avem de-a face cu un compilator de C++

__OBJC__: „C++ de la Apple”

__ASSEMBLER__:verifica daca prepocesarea se face in limbaj assembler

_WIN64: este sau nu compilator pentru Windows x64

_WIN32: este sau nu compilator pentru Windows x32

__APPLE__: rezulta cod executabil pentru Apple

__linux: verific daca sunt sub mediul Linux

__unix: verific daca sunt sub mediul Unix