Ada pola ketika berhadapan dengan array dan fungsi; awalnya agak sulit dilihat.
Ketika berhadapan dengan array, ada baiknya untuk mengingat hal-hal berikut: ketika ekspresi array muncul di sebagian besar konteks, jenis ekspresi secara implisit dikonversi dari "N-element array T" ke "pointer ke T", dan nilainya diatur untuk menunjuk ke elemen pertama dalam array. Pengecualian untuk aturan ini adalah ketika ekspresi array muncul sebagai operan dari &atausizeof operator, atau ketika itu adalah string literal digunakan sebagai initializer dalam deklarasi.
Jadi, ketika Anda memanggil fungsi dengan ekspresi array sebagai argumen, fungsi tersebut akan menerima pointer, bukan array:
int arr[10];
...
foo(arr);
...
void foo(int *arr) { ... }
Inilah sebabnya mengapa Anda tidak menggunakan &operator untuk argumen yang terkait dengan "% s" di scanf():
char str[STRING_LENGTH];
...
scanf("%s", str);
Karena konversi tersirat, scanf()menerima char *nilai yang menunjuk ke awal strarray. Ini berlaku untuk setiap fungsi yang disebut dengan ekspresi array sebagai argumen (hampir semua str*fungsi, *scanfdan *printffungsi, dll.).
Dalam praktiknya, Anda mungkin tidak akan pernah memanggil fungsi dengan ekspresi array menggunakan &operator, seperti pada:
int arr[N];
...
foo(&arr);
void foo(int (*p)[N]) {...}
Kode seperti itu sangat tidak umum; Anda harus mengetahui ukuran array dalam deklarasi fungsi, dan fungsi hanya bekerja dengan pointer ke array ukuran tertentu (pointer ke array 10-elemen T adalah jenis yang berbeda dari pointer ke array 11-elemen dari T).
Ketika ekspresi array muncul sebagai operan ke &operator, jenis ekspresi yang dihasilkan adalah "pointer ke array elemen-N dari T", atau T (*)[N], yang berbeda dari array pointer ( T *[N]) dan pointer ke tipe dasar (T * ).
Ketika berhadapan dengan fungsi dan pointer, aturan yang harus diingat adalah: jika Anda ingin mengubah nilai argumen dan memilikinya tercermin dalam kode panggilan, Anda harus meneruskan pointer ke hal yang ingin Anda modifikasi. Sekali lagi, array melemparkan sedikit kunci pas ke dalam karya, tetapi kita akan berurusan dengan kasus normal terlebih dahulu.
Ingatlah bahwa C lewat semua argumen fungsi dengan nilai; parameter formal menerima salinan nilai dalam parameter aktual, dan setiap perubahan pada parameter formal tidak tercermin dalam parameter aktual. Contoh umum adalah fungsi swap:
void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(a, b);
printf("after swap: a = %d, b = %d\n", a, b);
Anda akan mendapatkan output berikut:
sebelum swap: a = 1, b = 2
setelah swap: a = 1, b = 2
Parameter formal xdan yobjek berbeda dari adan b, sehingga berubah menjadi xdan ytidak tercermin dalam adan b. Karena kami ingin memodifikasi nilai adan b, kami harus meneruskan pointer ke fungsi swap:
void swap(int *x, int *y) {int tmp = *x; *x = *y; *y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("after swap: a = %d, b = %d\n", a, b);
Sekarang output Anda akan menjadi
sebelum swap: a = 1, b = 2
setelah swap: a = 2, b = 1
Perhatikan bahwa, dalam fungsi swap, kami tidak mengubah nilai xdan y, tetapi nilai apa xdan y menunjuk ke . Menulis ke *xberbeda dari menulis ke x; kami tidak memperbarui nilai xitu sendiri, kami mendapatkan lokasi dari xdan memperbarui nilai di lokasi itu.
Ini sama benarnya jika kita ingin memodifikasi nilai pointer; jika kita menulis
int myFopen(FILE *stream) {stream = fopen("myfile.dat", "r"); }
...
FILE *in;
myFopen(in);
maka kita memodifikasi nilai parameter input stream, bukan stream menunjuk ke apa , jadi mengubah streamtidak berpengaruh pada nilai in; agar ini berfungsi, kita harus meneruskan sebuah pointer ke pointer:
int myFopen(FILE **stream) {*stream = fopen("myFile.dat", "r"); }
...
FILE *in;
myFopen(&in);
Sekali lagi, array melemparkan sedikit kunci pas ke dalam karya. Saat Anda meneruskan ekspresi array ke suatu fungsi, fungsi yang diterima adalah sebuah pointer. Karena bagaimana array subscript didefinisikan, Anda bisa menggunakan operator subskrip pada pointer dengan cara yang sama Anda bisa menggunakannya pada array:
int arr[N];
init(arr, N);
...
void init(int *arr, int N) {size_t i; for (i = 0; i < N; i++) arr[i] = i*i;}
Perhatikan bahwa objek array mungkin tidak ditugaskan; yaitu, Anda tidak dapat melakukan sesuatu seperti
int a[10], b[10];
...
a = b;
jadi Anda ingin berhati-hati ketika berhadapan dengan pointer ke array; sesuatu seperti
void (int (*foo)[N])
{
...
*foo = ...;
}
tidak akan bekerja