Ce face #define
Înainte de compilarea propriu-zisă, fiecare fișier C trece prin preprocesor. Acesta execută liniile care încep cu #. #define TVA 0.21 îi spune preprocesorului: oriunde apare cuvântul TVA în cod, pune textul 0.21. Compilatorul nu vede niciodată numele TVA, ci doar valoarea.
Înlocuirea este pur textuală: preprocesorul nu știe tipuri și nu verifică nimic. De aceea o macro nu are tip, nu ocupă memorie și nu poate fi văzută în debugger. Prin convenție, numele de macro se scriu cu litere mari, ca să se vadă că nu sunt variabile. #undef NUME șterge definiția, iar opțiunea -DNUME=valoare a compilatorului definește o macro din linia de comandă, fără să modifici codul.
Compilatorul are și macro predefinite: __LINE__ (linia curentă), __FILE__ (numele fișierului), __STDC_VERSION__ (standardul folosit, de exemplu 202311L pentru C23), __DATE__ și __TIME__. Pentru constante cu tip, în C23 există și constexpr.
Parametri
| Parametru | Descriere |
|---|---|
NUME |
Identificatorul macro-ului. Prin convenție, cu litere mari: TVA, MAX_ELEVI. |
valoare |
Textul care înlocuiește numele, până la sfârșitul liniei. Poate lipsi: #define DEBUG definește doar numele (util pentru #ifdef). |
Exemple
Exemplul 1: Constante pentru un calcul de preț
TVA și MAX_PRODUSE sunt înlocuite în cod înainte de compilare. MAX_PRODUSE poate fi folosit chiar ca dimensiune de tablou, pentru că după înlocuire acolo scrie 3.
#include <stdio.h>
#define TVA 0.21
#define MAX_PRODUSE 3
int main(void) {
double preturi[MAX_PRODUSE] = {100.0, 45.5, 12.0};
for (int i = 0; i < MAX_PRODUSE; i++) {
printf("%.2f lei fără TVA -> %.2f lei cu TVA\n", preturi[i], preturi[i] * (1 + TVA));
}
return 0;
}
Rezultat
100.00 lei fără TVA -> 121.00 lei cu TVA
45.50 lei fără TVA -> 55.05 lei cu TVA
12.00 lei fără TVA -> 14.52 lei cu TVA
Exemplul 2: Macro predefinite și #undef
__STDC_VERSION__ are tipul long (de aceea %ld). După #undef ORAS, numele nu mai există, iar a doua definiție îl poate înlocui fără avertisment.
#include <stdio.h>
#define ORAS "Iași"
int main(void) {
printf("Standard C: %ld\n", __STDC_VERSION__);
printf("Linia curentă: %d\n", __LINE__);
printf("Oraș: %s\n", ORAS);
#undef ORAS
#define ORAS "Cluj-Napoca"
printf("Oraș nou: %s\n", ORAS);
return 0;
}
Rezultat
Standard C: 202311
Linia curentă: 7
Oraș: Iași
Oraș nou: Cluj-Napoca
Exemplul 3: Ce vede compilatorul după preprocesare
Opțiunea -E oprește compilarea după preprocesor și afișează codul rezultat (-P ascunde marcajele de linie). Se vede că numele macro au dispărut, înlocuite cu textul lor.
// pret.c
#define TVA 0.21
#define PRET_CU_TVA(p) ((p) * (1 + TVA))
double total = PRET_CU_TVA(100.0);
// în terminal:
// clang -E -P pret.c
Ieșire în terminal
double total = ((100.0) * (1 + 0.21));
Greșeli frecvente
- Pui punct și virgulă la final:
#define TVA 0.21;. Punctul și virgula devine parte din text, iarpret * TVA + 1se transformă înpret * 0.21; + 1, cu erori greu de înțeles. - Scrii o expresie fără paranteze:
#define TOTAL 10 + 5, apoiTOTAL * 2dă10 + 5 * 2= 20, nu 30. Pune mereu expresia între paranteze:#define TOTAL (10 + 5). - Folosești
#definepentru constante unde ar mergeconst,enumsauconstexpr. Acestea au tip, sunt verificate de compilator și apar în debugger.
Comenzi înrudite
Macro cu parametri: Macro care primesc argumente, ca o funcție: textul lor este copiat în locul apelului, cu operatorii # și ## și argumente variabile.#if, #ifdef, #ifndef: Compilare condiționată: preprocesorul păstrează sau elimină bucăți de cod în funcție de macro definite sau de valoarea lor.#include: Copiază conținutul unui fișier antet (.h) în locul liniei, ca funcțiile și tipurile declarate acolo să poată fi folosite.constexpr: Declară o constantă cu valoare calculată la compilare, cu tip, care poate fi folosită ca dimensiune de tablou sau în static_assert.const: Marchează o variabilă ca doar pentru citire: compilatorul oprește orice încercare de a o modifica.Compilarea cu gcc și clang: Cum transformi codul C într-un program executabil cu gcc sau clang și ce fac opțiunile folosite cel mai des.
Întrebări & Exemple de Cod:
#defineAi o nelămurire despre utilizarea comenzii
#definesau ai descoperit un truc / fragment de cod util? Distribuie-l cu ceilalți programatori!Fii primul care pune o întrebare sau distribuie un fragment de cod / prompt!
Nu au fost adăugate încă întrebări sau exemple de cod pentru această pagină. Dacă ai întâlnit o problemă sau ai un snippet util, adaugă-l mai jos pentru a-i ajuta pe ceilalți.