Achtergrond
Macro's met parameters zijn een belangrijk onderdeel van de C-preprocessor en zijn ontstaan voor het snel invoeren van herhalende codefragmenten en het vereenvoudigen van debugging. Ze worden gebruikt voor kleine functies, inlining of optimalisatie.
Probleem
Macro's controleren geen types en voeren geen volledige substitutie uit buiten simpele tekstvervanging. Fouten ontstaan door het ontbreken van haakjes en het substitueren van expressies met bijeffecten.
Oplossing
Zorg voor haakjes rond parameters en macro-definities, vermijd bijeffecten in argumenten en gebruik inline-functies voor complexere gevallen.
Voorbeeldcode:
#define MAX(a, b) ((a) > (b) ? (a) : (b)) int x = 5, y = 10; int z = MAX(x++, y++); // Gevaarlijke aanroep!
Belangrijkste kenmerken:
Vervangt de macro de code altijd volledig zoals een functie?
Nee! Een macro is slechts een tekstuele vervanging voordat de compilatie plaatsvindt en kan zich anders gedragen dan een functie als de argumenten expressies met bijeffecten zijn.
Kan elke aanroep (inclusief met ++, --) als parameter van de macro worden gebruikt?
Dit is uiterst gevaarlijk. Bijeffecten treden meerdere keren op als de parameter meer dan eens in de macro voorkomt.
Voorbeeldcode:
// Deze aanroep verhoogt x of y met meer dan 1 MAX(x++, y++)
Hoe moet je haakjes correct opnemen in macro-declaraties?
Zorg ervoor dat je zowel parameters als de expressie binnen de macro in haakjes plaatst om associativiteitsfouten bij aanroepen binnen andere expressies te voorkomen.
In het bedrijf was jarenlang de macro #define SQUARE(x) xx gedefinieerd en werd deze gebruikt voor expressies zoals SQUARE(a+1). Dit leidde tot ongewenste fouten: de expressie werd uitgepakt als a+1a+1, wat verschilt van (a+1)*(a+1).
Voordelen:
De macro SQUARE was geschreven met volledige haakjes: #define SQUARE(x) ((x)*(x)). Het gebruik ervan is gestandaardiseerd en gedocumenteerd.
Voordelen: