Programmeren in C/C-Preprocessor: verschil tussen versies

Verwijderde inhoud Toegevoegde inhoud
Regel 47:
</source>
 
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 omtrentover dit onderscheid. Het resultaat bestaat meestal uit rare compiler-foutmeldingen (de macro-expansie is immers prima gelukt) in stukken code die er verder primprima uitzien, of onverwacht gedrag in ''runtime''. Ervaring is recht evenredig met het aantal fouten dat je gemaakt hebt, zegt men dan.
 
Omdat sommige macro-definities vrij lang zijn, kunnen meerdere regels worden gebruikt. Dit wordt aangegeven door middel van een ''backslash'' ('''\''') direct voor het ''newline''-karakter. Dat wil zeggen dat na de ''backslash'' geen spaties of tabs meer mogen volgen. Technisch gesproken is dit "''escaping the newline''", het ontsnappen aan het nieuwe-regel-karakter. De backslash staat dan ook wel bekend als een ''escape''.
Regel 60:
</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.
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.
<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 '''HelloHELLO''' 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 73 ⟶ 83:
 
int fout = 5*FOUT(2); /* 5 * 2 * 2 + 1 = 21 (niet wat je verwachten zou...) */
int goednog_fouter = 5*GOEDFOUT(21+1); /* 5 * ( 2 * 21 + 1) =+ 51 *= 512 =(echt 25fout, 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.