programowanieProgramista C

Jakie są różnice między wskaźnikami a tablicami w języku C? Jak prawidłowo przekazywać tablicę do funkcji?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Wskaźniki i tablice w C są ze sobą powiązane, ale nie są tym samym:

  • Tablica — zbiór elementów tego samego typu w pamięci, określony rozmiarem.
  • Wskaźnik — zmienna przechowująca adres w pamięci, na który może wskazywać tablica lub pojedynczy obiekt.

Przy przekazywaniu tablicy do funkcji faktycznie przekazywany jest wskaźnik na pierwszy element tablicy (dlatego sizeof wewnątrz funkcji nie zwraca rozmiaru całej tablicy, a jedynie rozmiar wskaźnika).

Składnia przekazywania:

void foo(int arr[], int size) { // arr — faktycznie int* for (int i = 0; i < size; ++i) printf("%d ", arr[i]); } int main() { int data[5] = {1,2,3,4,5}; foo(data, 5); }

Pytanie z pułapką.

Pytanie: Co zwróci wyrażenie sizeof(arr) wewnątrz funkcji, jeśli arr to parametr typu int arr[]?

Odpowiedź: Zwraca rozmiar wskaźnika (sizeof(int*)), a nie rozmiar całej tablicy. Ponieważ do funkcji przekazywany jest wskaźnik na pierwszy element, informacja o długości zostaje utracona.

Przykład kodu:

void printSize(int arr[]) { printf("%zu ", sizeof(arr)); // sizeof(int*) zwykle 4 lub 8 }

Historia

W komercyjnym projekcie do obliczania średniej wartości w tablicy napisano kod, w którym do liczby elementów wewnątrz funkcji brano sizeof(arr) / sizeof(arr[0]), co zawsze zwracało 1 lub 2 zamiast rzeczywistej liczby elementów. Z powodu tego program nieprawidłowo działał z danymi, nieprawidłowo uśredniał wartości.


Historia

W pewnym projekcie dynamicznie alokowana tablica była przekazywana do funkcji bez osobnego przechowywania długości (size). W rezultacie funkcja nie wiedziała, ile elementów zostało alokowanych, co prowadziło do przekroczeń granic, wycieków lub uszkodzenia pamięci.


Historia

Przez pomyłkę użyto tablicy o stałym rozmiarze jako wskaźnika, a na niektórych kompilatorach dopuszczano bezpośrednie przypisanie przez memcpy całej tablicy zamiast jej elementów. To prowadziło do niejasnych błędów, gdy tracono części struktury danych lub następowało przepełnienie stosu.