Ce face #define
#define PI 3.14159 spune preprocesorului: „oriunde vezi PI, scrie 3.14159”. Înlocuirea este pur textuală și se face înainte de compilare: macro-urile nu au tip, nu respectă spațiile de nume și nu apar la depanare.
Un macro cu parametri (#define PATRAT(x) ((x) * (x))) arată ca o funcție, dar doar copiază text. De aceea fiecare parametru și întreaga expresie trebuie puse între paranteze. #x transformă parametrul în text, iar #undef NUME șterge definiția.
În C++ modern, pentru constante folosește constexpr, iar pentru „funcții mici” funcții inline/constexpr sau șabloane. #define rămâne util pentru compilare condiționată (#ifdef) și pentru câteva macro-uri predefinite: __cplusplus, __FILE__, __LINE__.
Exemple
Exemplul 1: Constantă și macro predefinit
__cplusplus spune standardul cu care se compilează: 202302 înseamnă C++23.
#include <print>
#define TVA 0.21
#define NUME_MAGAZIN "Librăria Iași"
int main() {
std::println("{}: preț cu TVA {:.2f} lei", NUME_MAGAZIN, 40 * (1 + TVA));
std::println("Standardul C++: {}", __cplusplus);
}
Rezultat
Librăria Iași: preț cu TVA 48.40 lei
Standardul C++: 202302
Exemplul 2: Capcana parantezelor
PATRAT_GRESIT(2 + 3) devine textul 2 + 3 * 2 + 3, adică 11, nu 25. Cu paranteze peste tot rezultatul este corect, iar funcția constexpr nu are deloc această problemă.
#include <print>
#define PATRAT_GRESIT(x) x * x
#define PATRAT(x) ((x) * (x))
constexpr int patrat(int x) { return x * x; }
int main() {
std::println("PATRAT_GRESIT(2 + 3) = {}", PATRAT_GRESIT(2 + 3));
std::println("PATRAT(2 + 3) = {}", PATRAT(2 + 3));
std::println("patrat(2 + 3) = {}", patrat(2 + 3));
}
Rezultat
PATRAT_GRESIT(2 + 3) = 11
PATRAT(2 + 3) = 25
patrat(2 + 3) = 25
Exemplul 3: Transformare în text (#) și #undef
#expr pune expresia între ghilimele, așa că macro-ul afișează și codul, și rezultatul. După #undef, numele AFISEAZA nu mai există.
#include <print>
#define AFISEAZA(expr) std::println("{} = {}", #expr, (expr))
int main() {
int note = 3;
AFISEAZA(note * 2 + 1);
AFISEAZA(10 / 4);
#undef AFISEAZA
#ifndef AFISEAZA
std::println("AFISEAZA nu mai este definit");
#endif
}
Rezultat
note * 2 + 1 = 7
10 / 4 = 2
AFISEAZA nu mai este definit
Greșeli frecvente
- Pui
;la final:#define MAX 100;. Punctul și virgula ajunge în cod la fiecare folosire (int v[MAX];devineint v[100;];). - Dai unui macro-funcție un argument cu efecte:
PATRAT(i++)devine((i++) * (i++)), deciicrește de două ori (și este comportament nedefinit). Funcțiile nu au această problemă. - Numești macro-urile ca pe variabile (
#define max 10). Strică orice alt cod care folosește numelemax, inclusivstd::max. Convenția este MAJUSCULE pentru macro-uri.
Comenzi înrudite
#ifdef, #ifndef, #if, #endif: Compilare condiționată: păstrează sau elimină bucăți de cod înainte de compilare, după ce macro-uri sunt definite.#include: Directivă a preprocesorului care copiază conținutul unui fișier antet în locul ei, ca să poți folosi funcțiile și clasele declarate acolo.constexpr: Cere ca o valoare să fie calculată la compilare; o funcție constexpr poate rula atât la compilare, cât și la rulare.inline: Permite ca o funcție sau variabilă să fie definită în mai multe fișiere (de obicei într-un antet) fără eroare de definiție dublă.