Programmeren in C/C-Preprocessor: verschil tussen versies

Verwijderde inhoud Toegevoegde inhoud
Regel 46:
#undef FOOBAR
</source>
 
Het verdient aanbeveling om in de code alle constanten met behulp van een macro te definiëren. Als ergens in de sourcecode ergens een getal '''10''' opduikt, is het niet duidelijk wat dat getal precies betekent. Door er met een macro een goed-gekozen naam aan te geven, is het onmiddelijk duidelijk welke functie die '''10''' heeft.
 
<source lang="c">
#define NUM_USERS 10
#define RECORD_SiZE 10
#define MAX_LOG_ENTRIES_PER_DAY 10
</source>
 
Als NUM_USERS veranderd (de directie heeft eindelijk besloten de stokoude, overbelaste server te vervangen) hoeft de waarde '''10''' maar op een plaats vervangen te worden. Als de '''10''' ''hardcoded'' in de broncode staat, moeten alle bestanden apart worden nagegaan en voor iedere '''10''' moet bekeken worden of het om het aantal gebruikers gaat, de afmetingen van een record of het maximum aantal log-meldingen per dag. Onnodig te vermelden dat dat een hoofdpijn-klus is. Lijstjes als hierboven (en vaak nog veel langere) zijn dan ook een vast onderdeel van de broncode.
 
Het is een goede gewoonte (en is bij professionele organisaties veplicht) om namen van macros uitsuiltend in ''uppercase'' te schrijven, ter onderscheiding van variabelen en functies. Iedere ervaren programmeur heeft zich al eens het hoofd gebroken over het onverwachtte gedrag dat voortvloeit uit verwarring over dit onderscheid. Het resultaat bestaat meestal uit rare compiler-foutmeldingen (de macro-expansie is immers prima gelukt) in stukken code die er verder prima uitzien, of onverwacht gedrag in ''runtime''. Ervaring is recht evenredig met het aantal fouten dat je gemaakt hebt, zegt men dan.
Regel 58 ⟶ 68:
#define HELLO(world) \
printf("Hello %s\n", world)
</source>
 
Het verdient aanbeveling om in de code alle constanten met behulp van een macro te definiëren. Als ergens in de sourcecode ergens een getal '''10''' opduikt, is het niet duidelijk wat dat getal precies betekent. Door er met een macro een goed-gekozen naam aan te geven, is het onmiddelijk duidelijk welke functie die '''10''' heeft.
 
<source lang="c">
#define NUM_USERS 10
#define RECORD_SiZE 10
#define MAX_LOG_ENTRIES_PER_DAY 10
</source>
 
Het is van belang te begrijpen dat het hier om tekstuele vervanging gaat. Als de boven gedefinieerde macro '''HELLO''' meermaals in de tekst wordt gebruikt, zal het ''printf''-statement evenzovele keren in de output-stream opduiken. Bij korte macro's is dit over het algemeen geen probleem,
maar in sommige gevallen zijn macro's er omvangrijk en kan veelvuldig gebruik een ''object-file'' opleveren die vele malen groter is dan verwacht. Verder zijn macro's, omdat het om een tekstuele vervanging gaat, soms lastig te volgen en te debuggen. Overdadig gebruik moet dan ook beslist worden afgeraden.
 
Als NUM_USERS veranderd (de directie heeft eindelijk besloten de stokoude, overbelaste server te vervangen) hoeft de waarde '''10''' maar op een plaats vervangen te worden. Als de '''10''' ''hardcoded'' in de broncode staat, moeten alle bestanden apart worden nagegaan en voor iedere '''10''' moet bekeken worden of het om het aantal gebruikers gaat, de afmetingen van een record of het maximum aantal log-meldingen per dag. Onnodig te vermelden dat dat een hoofdpijn-klus is. Lijstjes als hierboven (en vaak nog veel langere) zijn dan ook een vast onderdeel van de broncode.
 
Een tweede consequentie is dat als er een fout wordt gemaakt in de macro-definitie, de C-Compiler (en '''niet''' de C-Preprocessor!) een foutmelding zal geven op de plek waar de macro wordt gebruikt. Omdat op die plek alleen de macro-aanroep staat, die prima in orde is, en niet de macro definitie, kan dit zeer verwarrend werken.
Regel 82:
#define GOED(prima) (2*(prima)+1)
 
int fout = 5*FOUT(2); /* 5 * 2 * 2 + 1 = 21 (niet wat je verwachten zou...) */
int nog_fouter = 5*FOUT(1+1); /* 5 * 2 * 1 + 1 + 1 = 12 (echt fout, dus...) */
 
int goed = 5*GOED(2); /* 5 * ( 2 * (2) + 1) = 5 * 5 = 25 */
int ook_goed = 5*GOED(1+1); /* 5 * ( 2 * (1+1) + 1) = 5 * (2 * 2 + 1) = 5 * 5 = 25 */
 
</source>
Informatie afkomstig van https://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.