Apakah buruk untuk merujuk ke elemen array akses melalui aritmatika pointer alih-alih operator []?

12

Saya baru saja mulai belajar memprogram dalam C, dan untuk meningkatkan pemahaman saya tentang pointer dan array, saya mencoba merujuk pada elemen-elemen dari array tanpa membuat pointer sama sekali:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

Seluruh kode mengkompilasi dan berjalan dengan sempurna.

Saya membayangkan harus membuat pointer untuk setiap larik tunggal dalam kode sumber besar tampaknya sangat tidak efisien.

Jadi, daripada memiliki alamat array yang disimpan dan diambil dengan menggunakan pointer, apakah itu praktik pemrograman yang buruk untuk menggunakan alamat array secara langsung, seperti yang ditunjukkan di atas?

Niko Gambt
sumber
Menggunakan printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));akan menghindari pointer aritmik dan lebih mudah dimengerti.
Kasper van den Berg
1
Haha, kamu menangkapku. Saya melakukan itu hanya sebagai percobaan untuk mendapatkan pemahaman yang lebih baik tentang bagaimana pointer dan array bekerja.
Niko Gambt
Aritmatika pointer sebenarnya sekitar 30% lebih cepat daripada menggunakan indeks array.
Andy

Jawaban:

16

"Buruk" hanya sebatas yang kurang bisa dibaca. a[x]adalah hal yang sama dengan *(a+x), jadi tidak ada perbedaan dalam efisiensi atau perilaku (pada kenyataannya, x[a]juga akan berhasil). Hanya saja a[x]biasanya jauh lebih intuitif bagi kita manusia.

Tapi bukan berarti keterbacaan bukan masalah besar. Untuk melihat seberapa besar, pikirkan bagaimana Anda akan "membaca" dua ekspresi ini jika Anda melihatnya dalam kode:

  • *(a+x)= "Benda yang ditunjukkan oleh jumlah pointer adan integer x"
  • a[x]= " xAnggota array yang ke- a"

Demikian pula, ketika Anda perlu merujuk ke alamat elemen array:

  • (a+x)= "Jumlah pointer adan integer x"
  • &a[x]= "Alamat xanggota array yang ke- a"

Sebagian besar waktu, []versi hanya lebih mudah dipahami ketika Anda melihat kode non-sepele yang beroperasi pada beberapa array yang berbeda (terutama array array). Itu sebabnya []operator ada di tempat pertama.

PS Melakukan hal semacam ini secara ketat sebagai latihan belajar adalah ide yang sangat bagus. Sangat penting untuk memahami bahwa array benar-benar hanya pointer dan offset.

Ixrec
sumber
Ini. Terima kasih. Saya baru saja menyadari jauh di lubuk hati apa yang benar-benar ingin saya ketahui adalah apakah atau tidak, ketika ada kebutuhan untuk merujuk ke alamat elemen array, dan kemudian merujuk ke alamat elemen lain, dan kemudian yang lain, apakah masih buruk BUKAN menggunakan pointer dan, alih-alih, menggunakan array secara langsung seperti yang saya lakukan? Pertanyaan saya ini sangat sulit untuk ditunjukkan, itu sebabnya saya tidak mengetiknya di OP. Bagaimanapun, karena saya tidak menanyakannya, jawaban Anda memuaskan.
Niko Gambt
1
@NikoGambt Anda selalu dapat mengajukan pertanyaan lain =)
Ixrec
1
Apa yang Anda maksud hanya sebatas ...? Seluruh titik bahasa pemrograman adalah untuk membuat kode lebih mudah bagi manusia untuk membaca. Jika kita tidak peduli tentang itu, maka kita semua akan menulis kode op dalam heksadesimal.
Solomon Slow
2
Array bukan pointer, pembusukan hanya untuk pointer secara implisit.
CodesInChaos
4

Ya, ini praktik buruk, tetapi bukan karena alasan ketidakefisienan.

Operator array menggunakan arithmetric pointer di bawah kap, jadi keduanya sama-sama efisien.

Masalah dengan pointer arithmetric adalah sangat rentan kesalahan dan sulit dibaca.

Rule of thumb: Jangan gunakan pointer arithmetric kecuali Anda harus.

pengguna694733
sumber
1
Karena bagaimanapun juga menggunakan pointer aritmatika, bukankah itu berarti pointer juga sama-sama rawan kesalahan dan sulit dibaca?
Niko Gambt
1
@NikoGambt kompiler cukup baik dalam melakukan pointer arithmic di bawah tenda dan jarang akan membuat 'kesalahan'; itu adalah programmer yang akan membuat kesalahan dengan bug jahat sebagai konsekuensinya.
Kasper van den Berg
@KaspervandenBerg Ya, saya setuju. Namun, saya tertarik pada kesalahan yang dibuat oleh programmer, dan saya hanya tidak yakin apakah itu merupakan praktik pemrograman yang buruk untuk melakukan apa yang saya lakukan di sana, dalam kasus di mana ada kebutuhan untuk merujuk ke alamat array. , jika ada kasus seperti itu.
Niko Gambt
1
@NikoGambt Menulis sesuatu yang kurang dapat dibaca untuk tujuan kinerja hampir selalu merupakan praktik yang buruk, tetapi menulis sesuatu yang kurang dapat dibaca tanpa keuntungan adalah praktik yang benar - benar buruk.
Neil
@Neil Percobaan kecil saya tidak ada gunanya. Dengan melakukan itu, saya belajar bahwa kompiler sepertinya membuat array pointer untuk merujuk ke array multi-dimensi. Namun, karena Anda mengatakan keterbacaan lebih penting daripada kinerja, saya kira itu masih merupakan praktik pemrograman yang buruk.
Niko Gambt
0

Dinginkan pembelajaran Anda c, Anda baru saja menemukan salah satu dari twister lidah c. Anda tidak melakukan aritmatika pointer pada array, tetapi array pointer. Melakukan aritmatika pointer pada array tidak dimungkinkan. Array meluruh ke pointer tetapi bukan tipe pointer itu sendiri. Apa yang Anda miliki (lihat komentar oleh cmaster) adalah

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

Dereferencing pointer ini memberikan nilai pointer Anda yang baru dihitung, menunjuk ke. Biasanya tidak ada gunanya melakukan apa yang Anda lakukan. Tetapi Anda dapat membuat linear array dan kemudian melangkah di dalamnya, seperti ini.

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

Langkahnya adalah x_dim. Semoga jawaban saya jelas!

fhtuft
sumber
Tidak jelas dari OP apakah menggunakan int* array[ROW];an int array[ROW][COLUMN];, atau int (*array)[COLUMN];. Salah satu dari tiga definisi ini dapat digunakan dengan kode dalam OP.
cmaster - mengembalikan monica
ya saya sadar akan hal itu, jawaban saya agak canggung tentang hal itu. Saya memperbaikinya, terima kasih!
fhtuft