Обробка масивів C дуже відрізняється від Java, і вам доведеться відповідно налаштувати своє мислення. Масиви на C не є першокласними об'єктами (тобто вираз масиву не зберігає його "масив-ness" у більшості контекстів). У C вираз типу "N-елементний масив T" буде неявно перетворений ("розпад") у вираз типу "покажчик на T", за винятком випадків, коли вираз масиву є операндом операторів sizeofабо унарних &операторів, або якщо Вираз масиву - це рядковий літерал, який використовується для ініціалізації іншого масиву в декларації.
Крім усього іншого, це означає, що ви не можете передавати вираз масиву функції та отримувати його як тип масиву ; функція фактично отримує тип вказівника:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
У виклику до foo, вираз strперетворюється з типу char [6]в char *, тому перший параметр з fooоголошується char *aзамість char a[6]. В sizeof str, так як масив вираз є операндом sizeofоператора, він не перетвориться в тип покажчика, так що ви отримаєте кількість байтів в масиві (6).
Якщо вас справді цікавить, ви можете прочитати «Розвиток мови С» Денніса Річі, щоб зрозуміти, звідки походить таке лікування.
Підсумок полягає в тому, що функції не можуть повертати типи масивів, що добре, оскільки вирази масиву також не можуть бути ціллю призначення.
Найбезпечнішим методом є те, що абонент повинен визначити масив та передати його адресу та розмір функції, яка повинна йому написати:
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);
...
}
Інший спосіб полягає у функції динамічного розподілу масиву та повернення вказівника та розміру:
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);
...
}
У цьому випадку абонент відповідає за взаємодію масиву з freeфункцією бібліотеки.
Зауважте, що dstу наведеному вище коді є простим вказівником на char, а не вказівником на масив char. Семантика вказівника та масиву C є такою, що ви можете застосувати оператор []підрядника до виразу типу масиву або типу вказівника; обидва src[i]і dst[i]отримають доступ до i'-го елемента масиву (навіть якщо він srcмає лише тип масиву).
Ви можете оголосити вказівник на масив N-елементів Tі зробити щось подібне:
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]);
...
}
Кілька недоліків із вищезазначеним. Перш за все, старіші версії C очікують, що SOME_SIZEце буде константа часу компіляції, тобто ця функція буде працювати колись лише з одним розміром масиву. По-друге, вам слід знеструмити покажчик перед тим, як застосувати індекс, який захаращує код. Покажчики на масиви працюють краще, коли ви маєте справу з багатовимірними масивами.