programowanieProgramista C

Jak działa mechanizm przekazywania argumentów w funkcjach języka C? Jak unikać błędów typowych przy przekazywaniu zmiennych różnych typów, struktur i tablic?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W języku C argumenty w funkcjach zawsze są przekazywane przez wartość. Oznacza to, że funkcja otrzymuje kopię wartości argumentu. Dla podstawowych typów (int, float) jest to oczywiste: zmiany wewnątrz funkcji nie wpływają na oryginalną zmienną. Dla tablic i struktur są pewne niuanse:

  • Przy przekazywaniu tablicy do funkcji faktycznie przekazywany jest wskaźnik na jej pierwszy element, a nie cała tablica. Jednakże sam wskaźnik wciąż jest przekazywany przez wartość.
  • Dla struktur można jawnie przekazywać kopię (przez wartość), ale taką kopię lepiej robić przez wskaźnik — aby funkcja mogła modyfikować oryginalną strukturę.

Przykład: obróbka tablicy i struktury

#include <stdio.h> typedef struct { int a; int b; } Pair; void modifyArray(int arr[], int size) { arr[0] = 42; // modyfikuje oryginalną tablicę } void modifyStruct(Pair s) { s.a = 100; // zmienia tylko lokalną kopię } void modifyStructPtr(Pair *s) { s->a = 200; // zmienia oryginał przez wskaźnik } 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 ", nums[0], p.a); // nums[0]=42, p.a=200 return 0; }

Pytanie z podstępem.

Pytanie: Jeśli funkcja jest zadeklarowana jako void func(int arr[10]), czy ta tablica wewnątrz funkcji zawsze będzie miała 10 elementów?

Odpowiedź: Nie. Zapis int arr[10] w argumentach tak naprawdę jest równoważny int *arr — rozmiar tablicy gubi się podczas przekazywania. Funkcja nie zna rzeczywistej długości tablicy, dlatego zawsze przyjmuj dodatkowy parametr z jej długością. W przeciwnym razie mogą wystąpić nadmiarowe odwołania do pamięci i UB.

Przykład:

void foo(int arr[10]) { printf("%d ", arr[9]); // arr niekoniecznie zawiera 10 elementów! }

Historia

W projekcie do przetwarzania sygnałów przekazano tablicę przez funkcję, zakładając, że jej długość zawsze jest taka sama, ale w jednym przypadku przekazano mniejszą tablicę. Wynik — odwołanie poza zakres pamięci, awaria aplikacji oraz nieprzewidywalne zachowanie na kontrolerze.


Historia

W oprogramowaniu bankowym próbowano modyfikować strukturę, przekazując ją przez wartość, a nie przez wskaźnik. Zmiany nie były zapisywane, przez co moduł przetwarzający nie aktualizował stanu kont, co prowadziło do błędów w obliczeniach.


Historia

W systemie telemetrycznym student dodał funkcję czyszczenia tablicy, ale zapomniał przekazać długość, a tablice miały różne rozmiary. Błąd został odkryty dopiero po zebraniu dużej ilości niepoprawnych danych i długim czasie poszukiwania błędów.