preprocessor macro (tsz. preprocessor macros)
A makrók definiálásához a #define
direktívát használjuk.
#define PI 3.14159
#include <iostream>
using namespace std;
int main() {
cout << "A PI értéke: " << PI << endl;
return 0;
}
Itt a PI egy makró, amelyet a fordító minden előfordulásánál 3.14159-re cserél.
Makrók esetében: - Nincs típusa, így nem foglal memóriát. - Csak szöveges helyettesítés történik, nincs típusellenőrzés.
A makrók paramétereket is elfogadhatnak, így hasonlóak a függvényekhez.
#define OSSZEAD(a, b) (a + b)
#include <iostream>
using namespace std;
int main() {
cout << "5 + 3 = " << OSSZEAD(5, 3) << endl;
return 0;
}
A OSSZEAD(a, b)
minden előfordulásnál a + b
-re cserélődik.
Ha a makrót nem megfelelően zárójelezzük, helytelen működést eredményezhet:
#define SZORZAS(a, b) a * b
int x = SZORZAS(2, 3) + 4; // 2 * 3 + 4 → 6 + 4 = 10 (OK)
int y = SZORZAS(2, (3 + 4)); // 2 * (3 + 4) → 2 * 3 + 4 = 6 + 4 = 10 (Hibás!)
Megoldás: mindig használjunk zárójeleket:
#define SZORZAS(a, b) ((a) * (b))
A feltételes fordítás lehetővé teszi, hogy bizonyos kódrészek csak adott feltételek mellett kerüljenek a végső fordított kódba.
#ifdef
és #ifndef
#define DEBUG // Ha ezt kikommentezzük, akkor a debug üzenetek eltűnnek
#include <iostream>
using namespace std;
int main() {
#ifdef DEBUG
cout << "Debug mód bekapcsolva!" << endl;
#endif
cout << "Program fut..." << endl;
return 0;
}
Mit csinál? - Ha a DEBUG
makró meg van határozva (#define DEBUG
), akkor a debug üzenet bekerül a fordított kódba. - Ha nincs meghatározva, akkor a debug kódrészlet kimarad.
#if
, #elif
, #else
, #endif
#define VERZIO 2
#include <iostream>
using namespace std;
int main() {
#if VERZIO == 1
cout << "1. verzió fut!" << endl;
#elif VERZIO == 2
cout << "2. verzió fut!" << endl;
#else
cout << "Ismeretlen verzió!" << endl;
#endif
return 0;
}
Eredmény: Ha VERZIO
értéke 2, akkor a "2. verzió fut!"
üzenet jelenik meg.
#undef
)Makró törölhető a #undef
direktívával:
#define PI 3.14159
#undef PI // PI makró most törölve lett
Ezután a PI makró többé nem elérhető.
#pragma once
, #ifndef
)Makrókat gyakran használunk header fájlok védelmére, hogy a fájl ne legyen többször beillesztve.
#pragma once
(Egyszerűbb)#pragma once
void hello();
Ezzel elkerülhető a többszörös beillesztés.
#ifndef
és #define
#ifndef HEADER_FAJL
#define HEADER_FAJL
void hello();
#endif // HEADER_FAJL
Ez biztosítja, hogy ha a fájl már be volt illesztve, akkor ne ismétlődjön meg.
C++ néhány beépített makrót biztosít:
Makró | Jelentés |
---|---|
__FILE__
|
Az aktuális fájl neve |
__LINE__
|
Az aktuális sor száma |
__DATE__
|
A fordítás dátuma |
__TIME__
|
A fordítás időpontja |
__cplusplus
|
A C++ szabvány verziója |
Példa:
#include <iostream>
using namespace std;
int main() {
cout << "Fájl neve: " << __FILE__ << endl;
cout << "Sor száma: " << __LINE__ << endl;
cout << "Fordítás dátuma: " << __DATE__ << endl;
cout << "Fordítás ideje: " << __TIME__ << endl;
return 0;
}
A makrók nagy hátránya, hogy nincs típusellenőrzés és nehezebb hibakeresni őket.
Makró:
#define NEGYZET(x) ((x) * (x))
cout << NEGYZET(5) << endl; // 25
Inline függvény (jobb megoldás!):
inline int negyzet(int x) {
return x * x;
}
cout << negyzet(5) << endl;
Miért jobb az inline függvény? - Típusellenőrzés van (a makró nem ellenőrzi a típusokat). - Hibakeresés könnyebb. - Hatékony, mert a fordító helyettesíti a függvényt a hívás helyén.
Makró | Előnyök | Hátrányok |
---|---|---|
#define
|
Gyors, nincs memóriafoglalás | Nehezebb hibakeresni, nincs típusellenőrzés |
Paraméteres makrók | Függvényekhez hasonló használat | Zárójelezési problémák lehetnek |
Feltételes fordítás | Különböző kódrészletek ki/be kapcsolása | Túlzott használat bonyolíthatja a kódot |
#pragma once , #ifndef
|
Header fájl védelem | Egyes fordítók nem támogatják #pragma once -t
|
Beépített makrók | Hasznos fordítási információk | Limitált funkcionalitás |
A preprocessor makrók hasznosak konstansok, feltételes fordítás, kód rövidítés és header fájl védelem esetén. Mégis, sok esetben az inline függvények és a constexpr
jobb alternatívát jelentenek! 🚀