To, co mówisz w swoim poście, jest całkowicie poprawne. Powiedziałbym, że każdy programista C dochodzi do dokładnie tego samego odkrycia i do dokładnie tego samego wniosku, gdy (jeśli) osiągnie pewien poziom biegłości w języku C.
Gdy specyfika obszaru aplikacji wywołuje tablicę o określonym stałym rozmiarze (rozmiar tablicy jest stałą czasu kompilacji), jedynym właściwym sposobem przekazania takiej tablicy do funkcji jest użycie parametru wskaźnika do tablicy
void foo(char (*p)[10]);
(w języku C ++ odbywa się to również z odwołaniami
void foo(char (&p)[10]);
).
Umożliwi to sprawdzanie typu na poziomie języka, co zapewni, że tablica o dokładnie poprawnym rozmiarze zostanie dostarczona jako argument. W rzeczywistości w wielu przypadkach ludzie używają tej techniki niejawnie, nawet nie zdając sobie z tego sprawy, ukrywając typ tablicy za nazwą typedef
typedef int Vector3d[3];
void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);
Zauważ dodatkowo, że powyższy kod jest niezmienny w stosunku do Vector3d
typu będącego tablicą lub struct
. Możesz Vector3d
w dowolnym momencie przełączyć definicję z tablicy na a struct
iz powrotem, bez konieczności zmiany deklaracji funkcji. W obu przypadkach funkcje otrzymają obiekt zagregowany „przez odniesienie” (są od tego wyjątki, ale w kontekście tej dyskusji jest to prawdą).
Jednak nie zobaczysz tej metody przekazywania tablic używanej jawnie zbyt często, po prostu dlatego, że zbyt wielu ludzi jest zdezorientowanych dość zawiłą składnią i po prostu nie czuje się wystarczająco dobrze z takimi funkcjami języka C, aby używać ich poprawnie. Z tego powodu w przeciętnym prawdziwym życiu przekazywanie tablicy jako wskaźnika do jej pierwszego elementu jest bardziej popularnym podejściem. Po prostu wygląda na „prostsze”.
Ale w rzeczywistości użycie wskaźnika do pierwszego elementu do przekazywania tablic jest bardzo niszową techniką, sztuczką, która służy bardzo konkretnemu celowi: jego jedynym celem jest ułatwienie przekazywania tablic o różnej wielkości (tj. Rozmiar w czasie wykonywania) . Jeśli naprawdę potrzebujesz mieć możliwość przetwarzania tablic o rozmiarze w czasie wykonywania, to właściwym sposobem przekazania takiej tablicy jest użycie wskaźnika do jej pierwszego elementu z konkretnym rozmiarem dostarczonym przez dodatkowy parametr
void foo(char p[], unsigned plen);
W rzeczywistości w wielu przypadkach bardzo przydatna jest możliwość przetwarzania tablic o rozmiarze w czasie wykonywania, co również przyczynia się do popularności tej metody. Wielu programistów C po prostu nigdy nie napotyka (lub nigdy nie rozpoznaje) potrzeby przetwarzania tablicy o stałym rozmiarze, pozostając w ten sposób nieświadomymi właściwej techniki stałego rozmiaru.
Niemniej jednak, jeśli rozmiar tablicy jest stały, przekazanie jej jako wskaźnika do elementu
void foo(char p[])
jest głównym błędem technicznym, który niestety jest obecnie dość powszechny. W takich przypadkach znacznie lepszym podejściem jest technika typu wskaźnik do tablicy.
Innym powodem, który może utrudniać przyjęcie techniki przekazywania tablic o stałym rozmiarze, jest dominacja naiwnego podejścia do typowania tablic alokowanych dynamicznie. Na przykład, jeśli program wymaga ustalonych tablic typu char[10]
(jak w twoim przykładzie), przeciętny programista użyje malloc
takich tablic, jak
char *p = malloc(10 * sizeof *p);
Tej tablicy nie można przekazać do funkcji zadeklarowanej jako
void foo(char (*p)[10]);
co dezorientuje przeciętnego programistę i sprawia, że rezygnują z deklaracji parametru o stałym rozmiarze bez zastanawiania się nad tym. W rzeczywistości jednak źródłem problemu jest naiwne malloc
podejście. malloc
Format pokazano powyżej powinny być zarezerwowane dla tablic o rozmiarze run-time. Jeśli typ tablicy ma rozmiar w czasie kompilacji, lepszy sposób malloc
będzie wyglądał następująco
char (*p)[10] = malloc(sizeof *p);
Można to oczywiście łatwo przenieść na powyższe zadeklarowane foo
foo(p);
a kompilator przeprowadzi odpowiednie sprawdzenie typu. Ale znowu, jest to zbyt zagmatwane dla nieprzygotowanego programisty C, dlatego nie zobaczysz tego zbyt często w „typowym”, przeciętnym, codziennym kodzie.
10
można ją zastąpić dowolną zmienną w zakresie