Pertama, beberapa standar :
6.7.5.3 Deklarator fungsi (termasuk prototipe)
...
7 Deklarasi parameter sebagai '' array tipe '' harus disesuaikan ke '' penunjuk ke tipe yang memenuhi syarat
'', di mana kualifikasi tipe (jika ada) adalah yang ditentukan dalam [
dan ]
dari derivasi tipe array. Jika kata kunci static
juga muncul dalam [
dan]
dari derivasi tipe array, maka untuk setiap panggilan ke fungsi, nilai argumen aktual yang sesuai harus memberikan akses ke elemen pertama dari sebuah array dengan setidaknya sebanyak elemen yang ditentukan oleh ukurannya ekspresi.
Jadi, singkatnya, parameter fungsi apa pun yang dideklarasikan sebagai T a[]
atau T a[N]
diperlakukan seolah-olah dideklarasikan T *a
.
Jadi, mengapa parameter array diperlakukan seolah-olah dideklarasikan sebagai pointer? Inilah alasannya:
6.3.2.1 Lvalues, array, dan function designators
...
3 Kecuali jika itu adalah operan dari sizeof
operator atau operator unary &
, atau adalah string literal yang digunakan untuk menginisialisasi sebuah array, sebuah ekspresi yang memiliki tipe '' tipe array ' 'diubah menjadi ekspresi dengan tipe' 'pointer to type ' 'yang menunjuk ke elemen awal objek array dan bukan nilai l. Jika objek array memiliki kelas penyimpanan register, perilakunya tidak ditentukan.
Diberikan kode berikut:
int main(void)
{
int arr[10];
foo(arr);
...
}
Dalam panggilan ke foo
, ekspresi larikarr
bukanlah operand dari salah satu sizeof
atau &
, jadi tipenya secara implisit diubah dari "array 10-elemen int
" menjadi "pointer ke int
" menurut 6.2.3.1/3. Dengan demikian, foo
akan menerima nilai pointer, bukan nilai array.
Karena 6.7.5.3/7, Anda dapat menulis foo
sebagai
void foo(int a[]) // or int a[10]
{
...
}
tapi itu akan diartikan sebagai
void foo(int *a)
{
...
}
Jadi, kedua bentuk itu identik.
Kalimat terakhir di 6.7.5.3/7 diperkenalkan dengan C99, dan pada dasarnya berarti jika Anda memiliki deklarasi parameter seperti
void foo(int a[static 10])
{
...
}
parameter aktual yang sesuai dengan a
harus berupa larik dengan setidaknya 10 elemen.