Ce face Macro cu parametri
O macro cu parametri arată ca o funcție, dar nu este una. La #define PATRAT(x) ((x) * (x)), apelul PATRAT(nota) este înlocuit cu textul ((nota) * (nota)). Nu există apel, nu există verificare de tip, iar argumentul este copiat de câte ori apare în definiție.
Pentru că înlocuirea este textuală, pune paranteze în jurul fiecărui parametru și în jurul întregii expresii. Fără ele, PATRAT(2 + 3) devine 2 + 3 * 2 + 3 = 11. Între numele macro-ului și ( nu are voie să fie spațiu, altfel devine o macro simplă.
Operatorul # transformă un argument în șir de caractere (#x → "x"), iar ## lipește două cuvinte într-unul. Cu ... și __VA_ARGS__ (C99) o macro primește oricâte argumente; __VA_OPT__(,) (C23) pune virgula doar dacă există argumente. O macro cu mai multe instrucțiuni se scrie de obicei în do { ... } while (0), ca să se comporte ca o singură instrucțiune.
Parametri
| Parametru | Descriere |
|---|---|
#x |
Transformă argumentul în șir: TEXT(nota + 1) → "nota + 1". |
a##b |
Lipește cele două bucăți de text într-un singur nume: LIPESTE(nota, 1) → nota1. |
... |
Argumente variabile; în definiție se folosesc prin __VA_ARGS__. |
__VA_OPT__(text) |
C23: pune text doar dacă macro-ul a primit argumente variabile. |
Exemple
Exemplul 1: De ce sunt necesare parantezele
PATRAT_GRESIT(2 + 3) devine 2 + 3 * 2 + 3, adică 11. Varianta cu paranteze dă 25, cum te aștepți.
#include <stdio.h>
#define PATRAT_GRESIT(x) x * x
#define PATRAT(x) ((x) * (x))
int main(void) {
printf("Fără paranteze: %d\n", PATRAT_GRESIT(2 + 3));
printf("Cu paranteze: %d\n", PATRAT(2 + 3));
return 0;
}
Rezultat
Fără paranteze: 11
Cu paranteze: 25
Exemplul 2: Operatorii # și ## și o macro de jurnal
AFISEAZA(nota_ana) scrie și numele variabilei, și valoarea ei, datorită lui #. LOG primește un număr variabil de argumente; când nu primește niciunul, __VA_OPT__(,) nu pune virgula, deci printf primește doar formatul.
#include <stdio.h>
#define AFISEAZA(var) printf(#var " = %d\n", var)
#define CAMP(prefix, nume) prefix##nume
#define LOG(fmt, ...) printf("[jurnal] " fmt "\n" __VA_OPT__(,) __VA_ARGS__)
int main(void) {
int nota_ana = 10;
int CAMP(nota_, ion) = 8; // devine: int nota_ion = 8;
AFISEAZA(nota_ana);
AFISEAZA(nota_ion);
LOG("Catalog deschis");
LOG("Media: %.1f", (nota_ana + nota_ion) / 2.0);
return 0;
}
Rezultat
nota_ana = 10
nota_ion = 8
[jurnal] Catalog deschis
[jurnal] Media: 9.0
Exemplul 3: Argumentul evaluat de două ori
În MAX(i++, 3) textul i++ apare de două ori în expansiune, deci i crește de două ori. O funcție obișnuită (aici max_int) evaluează argumentul o singură dată.
#include <stdio.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))
static int max_int(int a, int b) {
return a > b ? a : b;
}
int main(void) {
int i = 5;
int m = MAX(i++, 3);
printf("macro: m = %d, i = %d\n", m, i);
int j = 5;
int n = max_int(j++, 3);
printf("funcție: n = %d, j = %d\n", n, j);
return 0;
}
Rezultat
macro: m = 6, i = 7
funcție: n = 5, j = 6
Greșeli frecvente
- Lași spațiu între nume și paranteză:
#define PATRAT (x) ((x)*(x)). Asta definește macro-ul simpluPATRATcu textul(x) ((x)*(x)). - Dai ca argument o expresie cu efecte (
i++, un apel de funcție). Dacă parametrul apare de două ori în definiție, efectul se produce de două ori. - Scrii o macro cu două instrucțiuni fără
do { ... } while (0). Într-uniffără acolade, doar prima instrucțiune ține deif; a doua se execută mereu. - Folosești o macro unde merge o funcție
static inline. Funcția are tipuri verificate, se poate depana și nu are probleme cu evaluarea dublă.
Comenzi înrudite
#define: Definește o macro: un nume pe care preprocesorul îl înlocuiește cu textul dat, înainte ca programul să fie compilat.typeof și auto: typeof dă tipul unei expresii, iar auto deduce tipul variabilei din valoarea inițială. Ambele sunt standard din C23.Funcții și prototipuri: Cum definești și declari funcții în C: tipul rezultatului, parametrii, prototipul și transmiterea argumentelor prin valoare.Funcții variadice (stdarg.h): Funcții cu număr variabil de argumente, ca printf: le citești pe rând cu va_start, va_arg și va_end din stdarg.h.#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.
Întrebări & Exemple de Cod:
Macro cu parametriAi o nelămurire despre utilizarea comenzii
Macro cu parametrisau 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.