Eeltranslaatori käsuga #define saab defineerida nii sümboolseid konstante kui ka makrosid. Selle käsu üldine kuju on järgmine:
#define <konstandi nimi> <väärtus>
Kohates sellist käsku, asendab eeltranslaator kõikjal programmi tekstist leitud vastavanimelised konstandid toodud väärtusega. Siinkohal on tegemist vaid teksti asendamisega. Kuidas sellest tekstist aru saada, seda peab juba tegelik translaator teadma.
Sümboolseid konstnte kasutasime juba näiteprogrammis INTEGRAL.
17. #define MINPIIR 0.0 18. #define MAXPIIR M_PI / 2.0 19. #define EPS 0.0001
Me oleksime võinud neid konstante ju ka otse programmi teksti sisestada, kuid nii on ülevaatlikum ja hiljem lihtsam nende konstantide väärtusi muuta. Märkida tuleb, et sümboolsete konstantide defineerimisel ei ole vaja lisada rea lõppu semikoolonit. Kui te seda siiski teete, siis käsitleb eeltranslaator seda semikoolonit kui makro osa ja sisestab ta igale poole teksti, kus te olete makrot kasutanud. See aga takistaks teil seda makrot mingis avaldises kasutamast, kuna lisatud semikoolon lõpetaks lause sellel kohal.
Makrosid defineeritakse samamoodi.
#define <makro nimi>(<parameetrite loetelu>) <asendav avaldis>
Makro on nagu tilluke funktsioon, mis erineb tegelikust funktsioonist selle poolest, et tema väljakutsumise puhul programmi käik ei muutu, vaid makro sisu lisatakse sellesse kohta programmi teksti. Kui te kasutatate makrot programmis mitu korda, siis lisatakse vastav kood ka sama palju kordi programmi teksti. Seepärast ei ole ka mõtet pikki makrosid luua. Nende mitmekordse kasutamise puhul läheks programm üsna suureks. Makro omab aga seda eelist, et tema kasutamine ei nõua alamprogrammi väljakutsumist koos parameetrite üleandmisega jne. ning on seetõttu kiirem. Lihtne makro näeks välja järgmiselt:
#define max(a, b) (a > b) ? a : b /* arvutab kahest arvust suurema */ #define min(a, b) (a < b) ? a : b /* arvutab kahest arvust väiksema*/
Makrod min() ja max() on juba defineeritud päisefailis STDLIB.H. Makro max() puhul asendatakse iga avaldis stiilis max(x, y) tekstiga (x > y) ? x : y. Makrode kasutamisel tuleb meeles pidada, et siin ei ole tegu funktsiooni kasutamisega, vaid teksti asendamisega. Kui max() oleks funktsioon, siis oleks valemis:
int k, j = 0, i = 1; ... k = max(i++, j);
tulemuseks 2 ja peale sellise funktsiooni kasutamist oleks muutuja i väärtuseks 1. Enne funktsiooni kasutamist suurendatakse ju muutuja i väärtust ühe võrra ja kuna 2 > 0, siis oleks tulemuseks 2. Kuna aga tegemist on teksti asendamisega, siis oleks peale asendamist avaldise välimus järgmine:
k = (i++ > j) ? i++ : j;
Nüüd täidetakse valemit i++ juba kaks korda ja seepärast on nii k kui ka i väärtusteks 3. Niisiis ei tohi (juhul kui te ei tea, kuidas see makro on implementeeritud) kasutada makro parameetritena avaldisi. Kui avaldis on nii pikk, et ta enam ühele reale ei mahu, siis tuleb otse enne klahvile <ENTER> vajutamist sisestada sümbol \. See sümbol (backslash) sunnib translaatorit ignoreerima järgnevat realõpumärki. Samal kombel saab ka teha üherealisest kommentaarist kaherealise.
Kui lisada makros parameetri nime ette sümbol #, siis tingib see parameetri väärtuse ilmumise asendatud tekstis jutumärkides. Näiteks:
#define TEXT(a) #a
...
printf("%s\n", "Tere hommikust" TEXT("Toomas"));
Tulemuseks oleks :
Tere hommikust "Toomas"
Defineeritud makro asendab kõigepealt teksti järgmiselt: "Tere hommikust" ""Toomas"". Iga järjestikku asuv jutumärkide paar defineerib ühe stringi. Praegusel hetkel oleks defineeritud kolm stringi ja nimi Toomas jääks üldse välja. Eeltranslaator on aga küllalt intelligentne lisamaks siia veel kaks sümbolit\. Seega on tulemuseks hoopiski: "Tere hommikust" "\"Toomas\"". Nüüd käsitletakse kahte jutumärki lihtsate sümbolitena ja stringi sel kohal ei lõpetata. Tulemuseks on aga ikkagi kaks stringi ja funktsiooni printf() formaadimäärangus oli määratud vaid üks. Kui nende kahe stringi vahel oleks koma, siis oleks tegu kahe erineva parameetriga ja viimast tõepoolest ekraanile ei ilmuks. Kuna neid aga ei ole komaga eraldatud, siis liidab translaator need kaks stringi üheks.
Lõpuks on võimalik makro parameetreid sümbolitega ## ühte liita. Operaator ## liidab kaks parameetrit üheks stringiks. Näiteks:
#define JADA(a, b) a ## b
...
printf("Tulemus on: %d\n", JADA(2, 4));
...
Tulemus on: 24
Siin moodustati kahest arvust uus arv. Tegemist ei olnud aga mingi matemaatilise tehtega. Nii saab ka kahest stringist moodustada uue stringi, mis võib olla ka näiteks funktsiooni või makro nimi. Näiteks:
printf("Tulemus on: %d\n", JADA("mi", "n(2, 4)"));
...
Tulemus on 4
Seekord moodustab makro JADA() kahest üleantud stringist uue stringi: min(2, 4), mis on omakorda makro. Eeltranslaator asendab seejärel ka selle makro temale vastava avaldisega ja tulemuseks on, et 4 > 2.