Sposób traktowania tablic w języku C bardzo różni się od sposobu traktowania w Javie i będziesz musiał odpowiednio dostosować swoje myślenie. Tablice w języku C nie są obiektami pierwszej klasy (to znaczy, że wyrażenie tablicowe nie zachowuje swojej „macierzy” w większości kontekstów). W języku C wyrażenie typu „tablica elementów N T” zostanie niejawnie przekonwertowane („rozpad”) na wyrażenie typu „wskaźnik do T”, z wyjątkiem sytuacji, gdy wyrażenie tablicowe jest operandem sizeofjednoargumentowym lub& operatorów lub, lub jeśli wyrażenie tablicowe to literał łańcuchowy używany do inicjalizacji innej tablicy w deklaracji.
Oznacza to między innymi, że nie można przekazać wyrażenia tablicowego do funkcji i odebrać je jako typ tablicowy ; funkcja faktycznie otrzymuje typ wskaźnika:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
W wywołaniu do foowyrażenie strjest konwertowane z typu char [6]na char *, dlatego zamiast parametru foodeklarowany jest pierwszy parametr . W , ponieważ wyrażenie tablicowe jest operandem operatora, nie jest konwertowane na typ wskaźnikowy, więc otrzymujesz liczbę bajtów w tablicy (6). char *achar a[6]sizeof strsizeof
Jeśli jesteś naprawdę zainteresowany, możesz przeczytać książkę Dennisa Ritchiego The Development of the C Language, aby zrozumieć, skąd pochodzi ta terapia.
W rezultacie funkcje nie mogą zwracać typów tablicowych, co jest w porządku, ponieważ wyrażenia tablicowe również nie mogą być celem przypisania.
Najbezpieczniejszą metodą jest zdefiniowanie przez wywołującego tablicy i przekazanie jej adresu i rozmiaru do funkcji, która ma do niej pisać:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
Inną metodą jest dynamiczne przydzielanie tablicy przez funkcję i zwracanie wskaźnika i rozmiaru:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
W tym przypadku wywołujący jest odpowiedzialny za zwolnienie tablicy za pomocą freefunkcji bibliotecznej.
Zauważ, że dstw powyższym kodzie jest prosty wskaźnik do char, a nie wskaźnik do tablicy char. Wskaźnik C i semantyka tablicy są takie, że można zastosować operator indeksu dolnego []do wyrażenia typu tablicowego lub typu wskaźnika; oba src[i]i dst[i]uzyskają dostęp do i'-tego elementu tablicy (nawet jeśli srcma tylko typ tablicy).
Państwo może zadeklarować wskaźnik do tablicy N-pierwiastkowej Ti zrobić coś podobnego:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
Kilka wad z powyższym. Po pierwsze, starsze wersje języka C oczekują, SOME_SIZEże będzie to stała czasu kompilacji, co oznacza, że funkcja będzie działać zawsze tylko z jednym rozmiarem tablicy. Po drugie, przed zastosowaniem indeksu dolnego należy usunąć odwołanie ze wskaźnika, który zaśmieca kod. Wskaźniki do tablic działają lepiej, gdy masz do czynienia z tablicami wielowymiarowymi.