programowanieProgramista C

Opowiedz szczegółowo o mechanizmie przekazywania tablic do funkcji w języku C. Jakie są ryzyka związane z tym modelem i jak prawidłowo zorganizować bezpieczną pracę z tablicami wewnątrz funkcji?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W języku C tablice nie są przekazywane do funkcji przez wartość. Jeśli przekażesz tablicę jako argument, do funkcji faktycznie trafia wskaźnik na pierwszy element tablicy. Prowadzi to do tego, że funkcja modyfikuje oryginalną tablicę, a nie jej kopię.

Na przykład:

void fillArray(int arr[], int n) { for (int i = 0; i < n; ++i) arr[i] = i*i; } int main() { int myarr[5]; fillArray(myarr, 5); // ok }

Wewnątrz funkcji:

  • nie można poznać rozmiaru oryginalnej tablicy przez sizeof(arr) — zwróci to rozmiar wskaźnika, a nie tablicy.
  • Można pracować tylko z tym fragmentem pamięci, którego rozmiar jawnie przekazaliśmy.

Aby poprawnie i bezpiecznie pracować z tablicami, możesz robić tak:

  • zawsze jawnie przekazuj rozmiar tablicy jako osobny argument;
  • używaj stałych lub makr opakowujących dla rozmiarów;
  • jeśli chcesz chronić tablicę przed zmianami, przekaż const int *arr.

Pytanie z pułapką

Pytanie: Czy można poznać rozmiar przekazanej tablicy wewnątrz funkcji przez argument int arr[] za pomocą sizeof(arr)?

Odpowiedź: Nie, nie można! sizeof(arr) wewnątrz funkcji zwróci rozmiar wskaźnika na typ (na przykład, 4 lub 8 bajtów), a nie rozmiar tablicy.

Przykład:

void f(int arr[]) { printf("%zu\n", sizeof(arr)); // rozmiar wskaźnika, nie tablicy! } int main() { int x[10]; f(x); // Zwykle zwróci 8 (x86_64) lub 4 (x86) }

Przykłady rzeczywistych błędów


Historia

W projekcie przemysłowym funkcje kopiowania tablic próbowały obliczać długość tablicy w locie, używając sizeof(arr)/sizeof(int) wewnątrz funkcji. W rezultacie prowadziło to do kopiowania tylko części tablicy, ponieważ rozmiar zawsze wynosił 1 (8/8), a dane były nadpisywane w nieprzewidywalny sposób.


Historia

W jednym z aplikacji sieciowych funkcja wysyłania danych przyjmowała bufor w postaci tablicy bez wyraźnego wskazania jego rozmiaru, przez co cały bufor nie zdążył się wysłać lub występowały odczyty śmieci poza granicami tablicy, co wywoływało błędy w przesyłaniu i niestabilność połączenia.


Historia

Przy pisaniu biblioteki do pracy z obrazami programista nie zaopatrzył funkcji kolorowania tablicy obrazów w obowiązkowy parametr rozmiaru. Doprowadziło to do przepełnienia bufora i awarii programu przy określonych danych wejściowych, co zostało wykryte dopiero w teście integracyjnym na dużym obrazie.