Apa perbedaan antara deklarasi berikut:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
Apa aturan umum untuk memahami deklarasi yang lebih kompleks?
c
arrays
pointers
variable-declaration
George
sumber
sumber
const
danvolatile
kualifikasi, yang penting dan sulit, tidak ada dalam artikel itu.Jawaban:
Yang ketiga sama dengan yang pertama.
Aturan umum adalah prioritas operator . Itu bisa menjadi jauh lebih kompleks ketika fungsi pointer masuk ke dalam gambar.
sumber
( ) [ ]
mengaitkan kiri ke kanan dan memiliki prioritas lebih tinggi daripada yang*
dibacaint* arr[8]
sebagai array ukuran 8 di mana setiap elemen menunjuk ke int danint (*arr)[8]
sebagai pointer ke array ukuran 8 yang menyimpan bilangan bulatGunakan program cdecl , seperti yang disarankan oleh K&R.
Cara kerjanya juga sebaliknya.
sumber
Saya tidak tahu apakah itu memiliki nama resmi, tetapi saya menyebutnya Right-Left Thingy (TM).
Mulai dari variabel, lalu ke kanan, dan ke kiri, dan ke kanan ... dan seterusnya.
arr1
adalah array 8 pointer ke integer.arr2
adalah pointer (tanda kurung blok kanan-kiri) ke array 8 bilangan bulat.arr3
adalah array 8 pointer ke integer.Ini akan membantu Anda keluar dengan deklarasi yang kompleks.
sumber
int *a[][10]
sementara yang kedua berhasil.( ) [ ]
dan kanan ke kiri* &
sumber
[5]
) mewakili dimensi bagian dalam. Ini berarti itu(*a[8])
adalah dimensi pertama, dan dengan demikian merupakan representasi luar array. Apa yang masing-masing elemen dalama
poin adalah array integer yang berbeda ukuran 5.Jawaban untuk dua yang terakhir juga dapat dikurangkan dari aturan emas dalam C:
int (*arr2)[8];
Apa yang terjadi jika Anda melakukan dereferensi
arr2
? Anda mendapatkan array 8 bilangan bulat.int *(arr3[8]);
Apa yang terjadi jika Anda mengambil elemen dari
arr3
? Anda mendapatkan pointer ke integer.Ini juga membantu ketika berhadapan dengan pointer ke fungsi. Untuk mengambil contoh sigjuice:
float *(*x)(void )
Apa yang terjadi ketika Anda melakukan dereferensi
x
? Anda mendapatkan fungsi yang dapat Anda panggil tanpa argumen. Apa yang terjadi ketika Anda menyebutnya? Ini akan mengembalikan pointer kefloat
.Namun, prioritas operator selalu rumit. Namun, menggunakan tanda kurung sebenarnya juga bisa membingungkan karena deklarasi mengikuti penggunaan. Setidaknya, bagi saya, secara intuitif
arr2
terlihat seperti array 8 pointer ke ints, tetapi sebenarnya sebaliknya. Hanya perlu membiasakan diri. Cukup beralasan untuk selalu menambahkan komentar pada deklarasi ini, jika Anda bertanya kepada saya :)edit: contoh
By the way, saya hanya menemukan situasi berikut: fungsi yang memiliki matriks statis dan yang menggunakan pointer aritmatika untuk melihat apakah pointer baris di luar batas. Contoh:
Keluaran:
Perhatikan bahwa nilai batas tidak pernah berubah, sehingga kompiler dapat mengoptimalkannya. Ini berbeda dari apa yang awalnya ingin Anda gunakan:
const int (*border)[3]
yang menyatakan perbatasan sebagai pointer ke array 3 bilangan bulat yang tidak akan mengubah nilai selama variabel ada. Namun, penunjuk itu dapat diarahkan ke array lain kapan saja. Kami menginginkan perilaku semacam itu untuk argumen, sebagai gantinya (karena fungsi ini tidak mengubah salah satu dari bilangan bulat itu). Deklarasi mengikuti penggunaan.(ps: jangan ragu untuk meningkatkan sampel ini!)
sumber
sumber
Sebagai aturan praktis, operator unary yang tepat (seperti
[]
,()
, dll) preferensi pengambilalihan yang kiri. Jadi,int *(*ptr)()[];
akan menjadi pointer yang menunjuk ke fungsi yang mengembalikan array pointer ke int (dapatkan operator yang tepat secepat mungkin setelah Anda keluar dari tanda kurung)sumber
error: ‘foo’ declared as function returning an array int foo(int arr_2[5][5])[5];
bawah GCC 8 dengan$ gcc -std=c11 -pedantic-errors test.c
int *(*ptr)();
memungkinkan ekspresi sepertip()[3]
(atau(*p)()[3]
) untuk digunakan nanti.int *foo(int arr_2[5][5]) { return &(arr_2[2][0]); }
dan menyebutnya seperti ini:foo(arr)[4];
yang seharusnya berisiarr[2][4]
, kan?Saya pikir kita bisa menggunakan aturan sederhana ..
"
ptr
adalah pointer untuk" pergi ke kanan .. itu ")" sekarang ke kiri a "(" keluar ke kanan "()" jadi "ke fungsi yang tidak memerlukan argumen" ke kiri "dan mengembalikan pointer" pergi kanan "ke larik" ke kiri "bilangan bulat"sumber
)
, sekarang ke kiri ... itu*
"pointer ke" ke kanan ... itu)
, sekarang ke kiri ... itu a(
keluar, ke kanan()
jadi "ke fungsi yang tidak memerlukan argumen" ke kanan ...[]
"dan mengembalikan array" ke kanan;
, jadi ke kiri ...*
"pointer ke" ke kiri ...int
"bilangan bulat"Berikut adalah situs web yang menarik yang menjelaskan cara membaca tipe kompleks di C: http://www.unixwiz.net/techtips/reading-cdecl.html
sumber
Inilah cara saya menafsirkannya:
Jadi, di sini kita akan menerapkan
[]
sebelumnya*
, membuat pernyataan setara dengan:Ini dapat dibaca sebagai, (nilai dari (nilai pada indeks ith dari sesuatu)) adalah bilangan bulat. Jadi, (nilai pada indeks ith dari sesuatu) adalah (integer pointer), yang menjadikan sesuatu array dari pointer integer.
Yang kedua,
Agar masuk akal dari pernyataan ini, Anda harus terbiasa dengan fakta ini:
Jadi, ganti
somethingElse
dengan(*something)
, kita dapatkan*(*something + i)
, yang merupakan bilangan bulat sesuai deklarasi. Jadi,(*something)
beri kami sebuah array, yang membuat sesuatu setara (pointer ke array) .sumber
Saya kira deklarasi kedua membingungkan banyak orang. Berikut cara mudah untuk memahaminya.
Mari kita memiliki array bilangan bulat, yaitu
int B[8]
.Mari kita juga memiliki variabel A yang menunjuk ke B. Sekarang, nilai pada A adalah B, yaitu
(*A) == B
. Karenanya A menunjuk ke array bilangan bulat. Dalam pertanyaan Anda, arr mirip dengan A.Demikian pula dalam
int* (*C) [8]
, C adalah pointer ke array pointer ke integer.sumber
Dalam deklarasi ini,
arr1
adalah array dari 5 pointer ke integer. Alasan: Kurung kotak lebih diutamakan daripada * (operator dereferncing). Dan dalam tipe ini, jumlah baris diperbaiki (5 di sini), tetapi jumlah kolom adalah variabel.Dalam deklarasi ini,
arr2
adalah pointer ke array integer dari 5 elemen. Alasan: Di sini, () kurung memiliki prioritas lebih tinggi dari []. Dan dalam tipe ini, jumlah baris adalah variabel, tetapi jumlah kolom adalah tetap (5 di sini).sumber
Dalam pointer ke integer jika pointer bertambah maka ia pergi integer berikutnya.
dalam array pointer jika pointer bertambah itu melompat ke array berikutnya
sumber