// Functie om het kwadraat van een getal te berekenen
int vierkant(int x) {
int resultaat =x * x;
// Postvoorwaarde:resultaat moet niet-negatief zijn (als x een geheel getal is)
beweren(resultaat>=0); // Dit kan mislukken vanwege een overflow van gehele getallen als x erg groot is.
resultaat retourneren;
}
int hoofd() {
int resultaat =vierkant(5);
printf("Vierkant van 5:%d\n", resultaat);
int groot_getal =100000; //Kan overstroming veroorzaken
resultaat =vierkant(groot_getal); // Postcondition kan mislukken vanwege overloop.
printf("Vierkant van %d:%d\n",groot_getal, resultaat);
retour 0;
}
```
In dit voorbeeld heeft de functie `vierkant` de postvoorwaarde dat `resultaat` niet-negatief moet zijn (ervan uitgaande dat `x` een geheel getal is). De instructie `assert(result>=0)` controleert deze postconditie. Als het resultaat negatief is (bijvoorbeeld vanwege een overflow van gehele getallen), mislukt de bewering.
Belangrijkste verschillen samengevat:
| Kenmerk | Voorwaarde | Postconditie |
| ---------------- | ----------------------------------------- | ------------------------------------------- |
| Tijd | *aangevinkt voordat* de functie | wordt uitgevoerd Aangevinkt *na* dat de functie wordt uitgevoerd |
| Verantwoordelijkheid | Beller van de functie | Functie zelf |
| Doel | Definieer verwachte input en omgeving | Definieer gegarandeerd gedrag en effect van de functie |
| Overtreding | Geeft een probleem aan met de *belcode* | Geeft een probleem aan *binnen de functie* |
| Garanties | De functie kan correct werken | De functie heeft het beoogde effect bereikt |
Hoe te implementeren in C:
Omdat C geen ingebouwde ondersteuning heeft voor pre- en postvoorwaarden, is de standaardaanpak het gebruik van:
1. `assert()` macro (van ``) :Dit is de meest gebruikelijke manier om de voorwaarden te controleren. Beweringen zijn doorgaans ingeschakeld in debug-builds (bijvoorbeeld met de `-DDEBUG` compilervlag) en uitgeschakeld in release-builds. Dit betekent dat de controles tijdens de ontwikkeling plaatsvinden, maar in het eindproduct worden geoptimaliseerd om prestatieoverhead te voorkomen.
2. `#ifdef DEBUG` blokken :Je kunt `#ifdef DEBUG` ook gebruiken om conditioneel complexere precondition- en postcondition-controles op te nemen die meer dan een eenvoudige vergelijking kunnen inhouden.
3. Opmerkingen :Zelfs als u geen beweringen gebruikt, is het van cruciaal belang om pre- en postcondities in opmerkingen te documenteren om uw code begrijpelijker te maken.
4. Frameworks testen: Overweeg het gebruik van testframeworks die pre-/post-conditiecontroles ondersteunen om het testen van eenheden te vergemakkelijken.
Voorbeeld met gecombineerde randvoorwaarden, postvoorwaarden en commentaar:
```c
#include
#include
/**
* @brief Berekent de macht van een getal (grondtal verheven tot exponent).
*
* @param base Het grondtalnummer (geheel getal).
* @param exponent De exponent (niet-negatief geheel getal).
*
* @pre exponent>=0 (Exponent mag niet-negatief zijn).
* @pre basis !=0 || exponent !=0 (basis en exponent niet beide 0 - vermijdt ongedefinieerd gedrag)
*
* @post Geeft basis verheven tot de macht van exponent.
* @post Als de exponent 0 is, is het resultaat 1 (behalve grondtal =0, wat niet is toegestaan).
*
* @return Het resultaat van het grondtal verheven tot de macht van de exponent.
* Geeft 1 terug als de exponent 0 is.
*/
int macht(int grondtal, int exponent) {
// Voorwaarden:
beweren(exponent>=0);
beweren(basis !=0 || exponent !=0); //Voorkom ongedefinieerd gedrag met 0^0
int-resultaat =1;
voor (int i =0; ik
resultaat *=basis;
}
// Postvoorwaarden:
als (exponent ==0) {
beweren(resultaat ==1); // Controleer op basisscenario
}
resultaat retourneren;
}
int hoofd() {
int resultaat =macht(2, 3); // 2^3 =8
printf("2^3 =%d\n", resultaat);
resultaat =macht(5, 0); // 5^0 =1
printf("5^0 =%d\n", resultaat);
//macht(0,0); // Dit zal de bewering activeren.
retour 0;
}
```
Voordelen van het gebruik van pre- en postvoorwaarden:
* Verbeterde codekwaliteit: Ze dwingen je om goed na te denken over de uitgangspunten en garanties van je functies.
* Gemakkelijker foutopsporing: Beweringen helpen fouten vroegtijdig op te sporen en de oorzaak van problemen te achterhalen.
* Betere documentatie: Ze documenteren duidelijk het verwachte gedrag van uw functies.
* Verhoogde onderhoudbaarheid: Ze maken uw code gemakkelijker te begrijpen en aan te passen, waardoor het risico op het introduceren van bugs wordt verkleind.
* Formele verificatie: In sommige gevallen kunnen pre- en postcondities worden gebruikt met formele verificatietools om de juistheid van uw code te bewijzen.
Door pre- en postcondities in uw C-code op te nemen (zelfs als u alleen maar opmerkingen en beweringen gebruikt), kunt u robuustere, betrouwbaardere en onderhoudbare software schrijven.