In de programmeertaal C zijn functieprototypes (function prototypes) de declaraties van functies die de compiler informeren over het retourtype, de naam en de parameter types van de functie vóór de feitelijke implementatie. Prototypes worden meestal geplaatst in headerbestanden (.h). Het gebruik ervan stelt ons in staat:
Voorbeeld van een prototype:
// math_utils.h int sum(int a, int b); // Prototype van de functie
// main.c #include "math_utils.h" int main() { int result = sum(3, 4); // de compiler kent de handtekening van sum }
Zonder het prototype zou de functie als een int worden beschouwd die een onbepaald aantal argumenten accepteert, wat kan leiden tot onverwachte runtime-fouten.
Vraag: Is het mogelijk om een functie in C aan te roepen voordat deze is gedefinieerd, als deze niet als prototype is gedeclareerd?
Antwoord: In de C89-standaard was het toegestaan om functies aan te roepen voordat ze zijn gedefinieerd, als de retourwaarde int was en er geen controles op de parameters waren (implicit int, implicit promotion). In moderne standaarden leidt dit tot waarschuwingen of fouten en dit zou niet moeten worden gebruikt.
Voorbeeld van een fout:
int main() { foo(1, 2); // Geen prototype voor foo } int foo(double x, double y) { ... }
De compiler zal de functie aanroepen, ervan uitgaande dat de parameters int zijn, terwijl de handtekening double impliceert — resultaat: UB of onjuiste waarden.
Verhaal
In een groot wetenschappelijk project ontbraken in een van de modules de prototypes voor functies voor gegevensverwerking. Bij het doorgeven van
floatin plaats vanintwerden de fouten pas na onjuiste berekeningen tijdens de exploitatie ontdekt, hoewel de compilatie zonder fouten verliep.
Verhaal
In een modulaire build-automatiseringstool werden functies alleen gedefinieerd in
.c-bestanden, zonder declaraties in headers. In twee modules waren functies gedefinieerd met dezelfde naam en incompatibele parameters — dit leidde tot een moeilijk te traceren fout bij het linken.
Verhaal
In een project voor embedded systemen deed zich een probleem voor: de initialisatiefunctie werd aangeroepen voordat deze was gedefinieerd zonder prototype. Door de aannames van de compiler over de parameter- en retourtypen werd de logica sterk verstoord en had het systeem alleen problemen bij bepaalde builds met verschillende geheugenschema's.