Wskaźniki i tablice w C są ze sobą powiązane, ale nie są tym samym:
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: 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.
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.