Pertanyaan Dengan array, mengapa kasusnya [5] == 5 [a]?


Seperti yang ditunjukkan oleh Joel Podcast Stack Overflow # 34, di Bahasa Pemrograman C (alias: K & R), ada yang menyebutkan properti array ini di C: a[5] == 5[a]

Joel mengatakan bahwa itu karena aritmatika penunjuk tapi aku masih tidak mengerti. Kenapa a[5] == 5[a]?


1427
2017-12-19 17:01


asal


Jawaban:


Standar C mendefinisikan [] operator sebagai berikut:

a[b] == *(a + b)

Karena itu a[5] akan mengevaluasi ke:

*(a + 5)

dan 5[a] akan mengevaluasi ke:

*(5 + a)

a adalah penunjuk ke elemen pertama dari larik. a[5] adalah nilai yang 5 elemen lebih jauh dari a, yang sama dengan *(a + 5), dan dari matematika sekolah dasar kita tahu mereka sama (selain itu komutatif).


1704
2017-12-19 17:04



Karena akses array didefinisikan dalam hal pointer. a[i] didefinisikan artinya *(a + i), yang bersifat komutatif.


273
2017-12-19 17:05



Saya pikir ada sesuatu yang terlewatkan oleh jawaban yang lain.

Iya nih, p[i] adalah dengan definisi yang setara dengan *(p+i), yang (karena penambahan adalah komutatif) setara dengan *(i+p), yang (sekali lagi, menurut definisi [] operator) setara dengan i[p].

(Dan masuk array[i], nama array secara implisit dikonversi ke pointer ke elemen pertama array.)

Tetapi komutatif penambahan tidak begitu jelas dalam kasus ini.

Ketika kedua operand memiliki tipe yang sama, atau bahkan dari berbagai jenis numerik yang dipromosikan ke tipe umum, komutatif masuk akal: x + y == y + x.

Tetapi dalam kasus ini kita berbicara secara khusus tentang aritmatika penunjuk, di mana satu operan adalah penunjuk dan yang lainnya adalah bilangan bulat. (Integer + integer adalah operasi yang berbeda, dan pointer + pointer tidak masuk akal.)

Deskripsi standar C tentang + operator (N1570 6.5.6) mengatakan:

Sebagai tambahan, kedua operand harus memiliki tipe aritmatika, atau satu   operan harus berupa penunjuk ke tipe objek lengkap dan lainnya   harus memiliki tipe integer.

Itu bisa saja dengan mudah mengatakan:

Sebagai tambahan, kedua operand harus memiliki tipe aritmatika, atau kiri   operan harus berupa penunjuk ke tipe objek lengkap dan operan kanan   harus memiliki tipe integer.

dalam hal ini keduanya i + p dan i[p] akan menjadi ilegal.

Dalam istilah C ++, kami benar-benar memiliki dua set kelebihan beban + operator, yang dapat digambarkan secara longgar sebagai:

pointer operator+(pointer p, integer i);

dan

pointer operator+(integer i, pointer p);

yang hanya yang pertama benar-benar diperlukan.

Jadi mengapa seperti ini?

C ++ mewarisi definisi ini dari C, yang mendapatkannya dari B (commutativity of array indexing secara eksplisit disebutkan pada tahun 1972 Referensi Pengguna ke B), yang mendapatkannya BCPL (manual tanggal 1967), yang mungkin mendapatkannya dari bahasa yang lebih awal (CPL? Algol?).

Jadi gagasan bahwa pengindeksan array didefinisikan dalam hal penambahan, dan penambahan itu, bahkan dari pointer dan integer, bersifat komutatif, berjalan kembali beberapa dekade, ke bahasa nenek moyang C.

Bahasa-bahasa itu jauh lebih diketik daripada bahasa C modern. Khususnya, perbedaan antara pointer dan bilangan bulat sering diabaikan. (Pemrogram C awal terkadang menggunakan pointer sebagai bilangan bulat yang belum ditandatangani, sebelum unsigned kata kunci ditambahkan ke bahasa.) Jadi ide membuat tambahan non-komutatif karena operand yang berbeda jenis mungkin tidak akan terjadi kepada para perancang dari bahasa tersebut. Jika seorang pengguna ingin menambahkan dua "hal", apakah "benda" itu adalah bilangan bulat, pointer, atau sesuatu yang lain, itu tidak sampai ke bahasa untuk mencegahnya.

Dan selama bertahun-tahun, setiap perubahan pada aturan itu akan merusak kode yang ada (meskipun standar ANSI C 1989 mungkin merupakan peluang yang baik).

Mengubah C dan / atau C ++ menjadi membutuhkan menempatkan pointer di sebelah kiri dan integer di sebelah kanan mungkin melanggar beberapa kode yang ada, tetapi tidak akan ada kehilangan daya ekspresif nyata.

Jadi sekarang kita punya arr[3] dan 3[arr] berarti hal yang persis sama, meskipun bentuk yang terakhir tidak boleh muncul di luar IOCCC.


186
2017-08-23 01:37



Dan tentu saja

 ("ABCD"[2] == 2["ABCD"]) && (2["ABCD"] == 'C') && ("ABCD"[2] == 'C')

Alasan utama untuk ini adalah bahwa pada tahun 70-an ketika C dirancang, komputer tidak memiliki banyak memori (64KB adalah banyak), sehingga compiler C tidak melakukan banyak pemeriksaan sintaks. Karenanya "X[Y]"agak buta diterjemahkan ke dalam"*(X+Y)"

Ini juga menjelaskan "+="dan"++"syntaxes. Segala sesuatu dalam bentuk"A = B + C"memiliki bentuk terkompilasi yang sama. Tapi, jika B adalah objek yang sama seperti A, maka tingkat optimasi assembly tersedia. Tetapi compiler tidak cukup terang untuk mengenalinya, jadi pengembang harus (A += C). Demikian pula, jika C adalah 1, optimasi tingkat perakitan yang berbeda tersedia, dan lagi-lagi pengembang harus membuatnya eksplisit, karena compiler tidak mengenalinya. (Kompiler baru-baru ini dilakukan, sehingga sebagian besar sintaksis ini tidak diperlukan hari ini)


184
2017-12-19 17:07



Satu hal yang tampaknya tidak disebutkan tentang masalah Dinah sizeof:

Anda hanya dapat menambahkan bilangan bulat ke penunjuk, Anda tidak dapat menambahkan dua tunjuk bersamaan. Dengan cara itu ketika menambahkan pointer ke integer, atau integer ke pointer, compiler selalu tahu bit mana yang memiliki ukuran yang perlu diperhitungkan.


51
2018-02-11 15:56



Untuk menjawab pertanyaan secara harfiah. Itu tidak selalu benar x == x

double zero = 0.0;
double a[] = { 0,0,0,0,0, zero/zero}; // NaN
cout << (a[5] == 5[a] ? "true" : "false") << endl;

cetakan

false

46
2017-08-11 13:50



Pertanyaan bagus / jawaban.

Hanya ingin menunjukkan bahwa C pointer dan array bukan sama, meskipun dalam hal ini perbedaannya tidak penting.

Pertimbangkan deklarasi berikut:

int a[10];
int* p = a;

Di a.out, simbol Sebuah berada di alamat yang merupakan awal dari array, dan simbol p berada di alamat tempat penunjuk disimpan, dan nilai penunjuk di lokasi memori itu adalah awal dari larik.


23
2017-12-20 08:16