In de C-taal worden argumenten in functies altijd per waarde doorgegeven. Dit betekent dat de functie een kopie van de waarde van het argument ontvangt. Voor eenvoudige types (int, float) is dit voor de hand liggend: veranderingen binnen de functie beïnvloeden de originele variabele niet. Voor arrays en structuren zijn er nuances:
Voorbeeld: verwerking van een array en een structuur
#include <stdio.h> typedef struct { int a; int b; } Pair; void modifyArray(int arr[], int size) { arr[0] = 42; // wijzigt de originele array } void modifyStruct(Pair s) { s.a = 100; // verandert alleen de lokale kopie } void modifyStructPtr(Pair *s) { s->a = 200; // wijzigt het origineel via de pointer } int main() { int nums[2] = {1, 2}; Pair p = {10, 20}; modifyArray(nums, 2); modifyStruct(p); modifyStructPtr(&p); printf("nums[0]=%d, p.a=%d\n", nums[0], p.a); // nums[0]=42, p.a=200 return 0; }
Vraag: Als een functie is gedeclareerd als void func(int arr[10]), heeft deze array binnen de functie altijd 10 elementen?
Antwoord: Nee. De notatie int arr[10] in de argumenten is in feite gelijk aan int *arr — de grootte van de array gaat verloren bij het doorgeven. De functie weet de echte lengte van de array niet, dus neem altijd een extra parameter voor de lengte mee. Anders kunnen er geheugenoverlopen plaatsvinden en UB ontstaan.
Voorbeeld:
void foo(int arr[10]) { printf("%d\n", arr[9]); // arr bevat niet per se 10 elementen! }
Geschiedenis
In een project voor signaalverwerking werd een array door een functie doorgegeven, met de gedachte dat de lengte altijd hetzelfde was, maar in één geval werd een kleinere array doorgegeven. Het resultaat — het aanspreken van geheugengebieden buiten de grenzen, het laten crashen van de applicatie en het ontstaan van onvoorspelbaar gedrag op de controller.
Geschiedenis
In banksoftware werd geprobeerd een structuur te wijzigen door deze per waarde door te geven in plaats van per pointer. Wijzigingen werden niet opgeslagen, waardoor de verwerkingseenheid de status van de rekeningen niet bijwerkte, leidend tot rekenfouten.
Geschiedenis
In een telemetriesysteem voegde een student een functie toe om een array te wissen, maar vergat de lengte door te geven, en de arrays waren van verschillende afmetingen. De fout werd pas ontdekt na het verzamelen van een grote hoeveelheid onjuiste gegevens en een lange tijd van bugopsporing.