1. Makrode põhialused
1.1 Makrode defineerimine ja kasutamine
C keeles defineeritakse makrosid #define
direktiiviga. Makro võimaldab asendada programmi sees teatud stringi konkreetse väärtuse või avaldisega. Näiteks kui kasutada programmis tihti samu konstandeid või keerulisi avaldisi, aitab makro nende defineerimisel parandada koodi loetavust ja hooldatavust.
#define PI 3.14159
#define SQUARE(x) ((x) * (x))
Ülaltoodud näites on defineeritud konstantmakro PI
ja funktsioonimakro SQUARE
. PI
asendatakse programmis väärtusega 3.14159 ning SQUARE(x)
asendatakse antud argumendi x
ruuduga.
1.2 Makrode ja muutujate erinevus
Makrosid töötleb preprotsessor kompileerimise ajal ning need toimivad puhtalt tekstilise asendusena. Muutujad aga hallatakse mälus programmi käivitamisel ja nende kasutamine nõuab rohkem ressursse. Kuna makrodel puudub tüüp, saab neid kasutada väga paindlikult erinevate andmetüüpidega, kuid samas puudub tüüpkontroll, mis võib viia vigadele vale kasutamise korral.
2. Tingimuslikud makrod
2.1 #if
, #ifndef
, #ifdef
kasutamine
Tingimuslikud makrod võimaldavad #if
, #ifndef
, #ifdef
direktiividega kontrollida, kas teatud koodiplokk kompileeritakse või mitte, sõltuvalt tingimustest.
#define DEBUG 1
#if DEBUG
printf("Debug-režiim\n");
#endif
Selles näites kompileeritakse printf
-lause ainult siis, kui DEBUG
on defineeritud. #ifdef
kontrollib, kas makro on defineeritud, ning #ifndef
kasutatakse, kui makro EI ole defineeritud.
2.2 Tingimuslike makrode kasutusvaldkonnad
Tingimuslikke makrosid kasutatakse sageli silumiskoodi (debug code) lihtsamaks haldamiseks. Samuti on need kasulikud platvormispetsiifilise koodi kirjutamisel või juhul, kui kompileerimisvalikud nõuavad erinevaid töötlusi.
3. Funktsioonimakrod
3.1 Funktsioonimakrode defineerimine ja kasutamine
Funktsioonimakrod on makrod, mis võtavad argumente ja neid saab kasutada tavapäraste funktsioonide sarnaselt. Funktsioonimakrod võimaldavad teha operatsioone sõltumata andmetüübist.
#define MAX(a, b) ((a) > (b) ? (a) : (b))
See näide defineerib funktsioonimakro MAX(a, b)
, mis tagastab kahe väärtuse hulgast suurema. MAX
on kasutatav suvaliste tüüpide puhul ja võimaldab leida maksimaalse väärtuse sõltumata tüübist.
3.2 Funktsioonimakrode eelised ja puudused
Funktsioonimakrode eeliseks on, et neid saab kasutada erinevate tüüpidega ilma piiranguteta. Kuid puuduseks on tüüpkontrolli puudumine – vale argumentide korral vigu ei kuvata. Samuti on funktsioonimakrosid raskem siluda ning keeruliste avaldiste puhul võib tekkida ootamatut käitumist.

4. Makrode praktilised näited
4.1 Silumiskoodi lisamine ja eemaldamine
Makrosid kasutatakse sageli selleks, et lihtsustada silumiskoodi lubamist või keelamist. Näiteks võib debug-režiimis lisada logisid ning eemaldada need lõppversioonis.
#ifdef DEBUG
#define LOG(x) printf(x)
#else
#define LOG(x)
#endif
Selles näites on LOG
makro aktiivne ainult siis, kui DEBUG
on defineeritud, ning printf
käivitatakse ainult sellisel juhul. Lõppversioonis saab DEBUG
defineeringu eemaldada ning logisid ei prindita enam välja.
4.2 Tingimusliku koodi kirjutamine
Platvormipõhise koodi puhul kasutatakse sageli tingimuslikke makrosid, et tagada ühilduvus erinevate keskkondadega.
#ifdef _WIN32
printf("Töötab Windowsis\n");
#else
printf("Töötab muus keskkonnas\n");
#endif
See kood käivitab teatud käsu ainult Windowsi keskkonnas, mujal aga mõne muu käsu. Tingimuslike makrode kasutamine aitab parandada koodi teisaldatavust ja hooldatavust.
5. Makrode kasutamise tähelepanekud
5.1 Makrode puudused
Makrod on küll väga võimsad, kuid nende kasutamisel tuleb olla ettevaatlik. Eriti funktsioonimakrod võivad ilma tüüpkontrollita põhjustada vigu, kui kasutatakse valesid argumente. Samuti on pärast makro lahtiharutamist raskem koodi siluda, mis võib raskendada vigade leidmist.
5.2 Ohutu makrokasutuse juhised
Makrode ohutuks kasutamiseks tuleks järgida järgmisi põhimõtteid.
- Kasuta makronimedes alati suuri tähti, et need eristuksid tavalistest muutujatest ja funktsioonidest.
- Väldi keeruliste avaldiste defineerimist makrona – kasuta vajadusel tavalisi funktsioone.
- Lisa makro kasutamisel alati selgitav kommentaar, mis kirjeldab selle eesmärki ja kasutust.
5.3 Parimad praktikad makrodele koodireeglites
Projektipõhistes koodireeglites määratletakse sageli makrode kasutamise juhised. Näiteks soovitatakse piirata funktsioonimakrode kasutamist ning eelistada konstantmakrosid. Kui võimalik, defineeri konstandid const
abil ning kasuta makrosid vaid vajadusel.
6. Kokkuvõte
C-keele makrod on olulised tööriistad koodi efektiivsuse ja loetavuse parandamiseks. Samas võivad võimsad makrod vale kasutuse korral põhjustada ootamatuid vigu. Selles artiklis käsitlesime makrode põhialuseid, praktilisi näiteid ja turvalise kasutamise soovitusi. Õige makrokasutus aitab kirjutada efektiivset ja hooldatavat koodi.