Perlakuan C pada array sangat berbeda dari Java, dan Anda harus menyesuaikan pemikiran Anda. Array dalam C bukan objek kelas satu (yaitu, ekspresi array tidak mempertahankannya "array-ness" dalam sebagian besar konteks). Dalam C, ekspresi tipe "N-element array T
" akan secara implisit dikonversi ("decay") menjadi ekspresi tipe "pointer to T
", kecuali ketika ekspresi array adalah operan dari operator sizeof
atau unary &
, atau jika ekspresi array adalah string literal yang digunakan untuk menginisialisasi array lain dalam deklarasi.
Di antara hal-hal lain, ini berarti bahwa Anda tidak dapat meneruskan ekspresi array ke suatu fungsi dan menerimanya sebagai tipe array ; fungsi sebenarnya menerima tipe pointer:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
Dalam panggilan ke foo
, ekspresi str
dikonversi dari tipe char [6]
ke char *
, itulah sebabnya parameter pertama foo
dideklarasikan char *a
daripada char a[6]
. Dalam sizeof str
, karena ekspresi array adalah operan dari sizeof
operator, itu tidak dikonversi ke tipe pointer, sehingga Anda mendapatkan jumlah byte dalam array (6).
Jika Anda benar - benar tertarik, Anda dapat membaca buku The Development of the C Dennis Ritchie untuk memahami dari mana perawatan ini berasal.
Hasilnya adalah bahwa fungsi tidak dapat mengembalikan tipe array, yang baik karena ekspresi array tidak dapat menjadi target penugasan, baik.
Metode teraman bagi penelepon untuk menentukan array, dan meneruskan alamat dan ukurannya ke fungsi yang seharusnya ditulis untuk itu:
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);
...
}
Metode lain adalah untuk fungsi untuk mengalokasikan array secara dinamis dan mengembalikan pointer dan ukuran:
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);
...
}
Dalam hal ini, pemanggil bertanggung jawab untuk membatalkan alokasi array dengan free
fungsi perpustakaan.
Perhatikan bahwa dst
dalam kode di atas adalah penunjuk sederhana char
, bukan penunjuk ke array char
. Pointer dan semantik array C sedemikian rupa sehingga Anda dapat menerapkan operator subskrip []
ke ekspresi tipe array atau tipe pointer; keduanya src[i]
dan dst[i]
akan mengakses i
elemen larik array (walaupun hanya src
memiliki tipe larik).
Anda dapat mendeklarasikan pointer ke array elemen-N T
dan melakukan sesuatu yang serupa:
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]);
...
}
Beberapa kekurangan dengan di atas. Pertama-tama, versi C yang lebih lama diharapkan SOME_SIZE
sebagai konstanta waktu kompilasi, artinya fungsi hanya akan bekerja dengan satu ukuran array. Kedua, Anda harus melakukan dereferensi pointer sebelum menerapkan subskrip, yang mengacaukan kode. Pointer ke array bekerja lebih baik ketika Anda berurusan dengan array multi-dimensi.