[Sebagai catatan, saya telah mengedit jawaban ini dengan cukup signifikan sejak diterima dan dipilih. Tapi pada dasarnya masih mengatakan hal yang sama.]
Kode ini sangat, mungkin sengaja, membingungkan. Ini berisi contoh sempit dari perilaku yang tidak terdefinisi ketakutan . Pada dasarnya tidak mungkin untuk menentukan apakah orang yang menyusun pertanyaan ini sangat, sangat pintar atau sangat, sangat bodoh. Dan "pelajaran" kode ini mungkin dimaksudkan untuk mengajarkan atau menanyai Anda tentang - yaitu, bahwa operator plus unary tidak berbuat banyak - tentu saja tidak cukup penting untuk pantas mendapatkan jenis penyesatan subversif semacam ini.
Ada dua aspek kode yang membingungkan, kondisi aneh:
while(+(+k--)!=0)
dan pernyataan gila yang dikontrolnya:
k=k++;
Saya akan membahas bagian kedua terlebih dahulu.
Jika Anda memiliki variabel seperti kyang ingin Anda tambahkan 1, C memberi Anda bukan satu, bukan dua, bukan tiga, tetapi empat cara berbeda untuk melakukannya:
k = k + 1
k += 1
++k
k++
Terlepas dari karunia ini (atau mungkin karena itu), beberapa programmer menjadi bingung dan batuk seperti contortions
k = k++;
Jika Anda tidak tahu apa yang harus dilakukan, jangan khawatir: tidak ada yang bisa. Ungkapan ini berisi dua upaya berbeda untuk mengubah knilai ( k =bagian, dan k++bagian), dan karena tidak ada aturan dalam C untuk mengatakan mana dari percobaan modifikasi yang "menang", ungkapan seperti ini secara resmi tidak ditentukan , artinya tidak hanya itu telah ada didefinisikan arti, tetapi bahwa seluruh program yang berisi itu adalah tersangka.
Sekarang, jika Anda melihat dengan sangat hati-hati, Anda akan melihat bahwa dalam program khusus ini, garis k = k++tidak benar-benar dieksekusi, karena (seperti yang akan kita lihat) kondisi pengendalian pada awalnya salah, sehingga loop berjalan 0 kali . Jadi program khusus ini mungkin sebenarnya tidak terdefinisi - tetapi masih membingungkan secara patologis.
Lihat juga jawaban SO kanonik ini untuk semua pertanyaan tentang Perilaku Tidak Terdefinisi dari jenis ini.
Tetapi Anda tidak bertanya tentang k=k++bagian itu. Anda bertanya tentang bagian pertama yang membingungkan, +(+k--)!=0kondisinya. Ini terlihat aneh, karena ini aneh. Tidak seorang pun akan pernah menulis kode seperti itu dalam program nyata. Jadi tidak ada alasan untuk belajar bagaimana memahaminya. (Ya, itu benar, menjelajahi batas-batas suatu sistem dapat membantu Anda belajar tentang poin-poin baiknya, tetapi ada garis yang cukup jelas dalam buku saya antara eksplorasi imajinatif, yang membangkitkan pikiran versus eksplorasi yang dangkal, eksplorasi yang kasar, dan ungkapan ini sangat jelas pada sisi yang salah dari garis itu.)
Bagaimanapun, mari kita periksa +(+k--)!=0. (Dan setelah melakukannya, mari kita lupakan semuanya.) Ekspresi seperti ini harus dipahami dari dalam ke luar. Saya kira Anda tahu apa
k--
tidak. Dibutuhkan knilai saat ini dan "mengembalikan" ke seluruh ekspresi, dan kurang lebih secara bersamaan menurun k, yaitu, ia menyimpan kuantitas k-1kembali k.
Tapi lalu apa fungsinya +? Ini plus unary , bukan plus biner. Ini seperti minus unary. Anda tahu bahwa minus biner tidak mengurangi: ekspresi
a - b
kurangi b dari a. Dan Anda tahu bahwa minus unary meniadakan hal-hal: ekspresi
-a
memberi Anda negatif a. Yang +dilakukan unary adalah ... pada dasarnya tidak ada. +amemberi Anda anilai, setelah mengubah nilai positif menjadi positif dan negatif menjadi negatif. Begitu ekspresinya
+k--
memberi Anda apa pun yang k--memberi Anda, itu adalah knilai lama.
Tapi kita belum selesai, karena sudah
+(+k--)
Ini hanya mengambil apa pun yang +k--memberi Anda, dan berlaku unary +untuk itu lagi. Jadi itu memberi Anda apa pun yang +k--memberi Anda, apa pun yang k--memberi Anda, yang merupakan knilai lama.
Jadi pada akhirnya, kondisinya
while(+(+k--)!=0)
melakukan hal yang persis sama dengan kondisi yang jauh lebih biasa
while(k-- != 0)
akan dilakukan. (Itu juga melakukan hal yang sama dengan kondisi yang terlihat lebih rumit while(+(+(+(+k--)))!=0). Dan kurung itu tidak benar-benar diperlukan; itu juga melakukan hal yang sama seperti yang while(+ + + +k--!=0)seharusnya dilakukan.)
Bahkan mencari tahu apa kondisi "normal"
while(k-- != 0)
Apakah agak rumit. Ada dua hal yang terjadi dalam loop ini: Karena loop berpotensi berulang kali, kita akan:
- terus lakukan
k--, untuk membuat klebih kecil dan lebih kecil, tetapi juga
- tetap melakukan body of the loop, apa pun yang dilakukannya.
Tapi kami melakukan k--bagian itu segera, sebelum (atau dalam proses) memutuskan apakah akan melakukan perjalanan lain melalui loop. Dan ingat bahwa k--"mengembalikan" nilai lama k, sebelum menurunkannya. Dalam program ini, nilai awal kadalah 0. Jadi k--akan "mengembalikan" nilai lama 0, lalu memperbarui kke -1. Tapi kemudian kondisi lainnya adalah != 0- tetapi seperti yang baru saja kita lihat, pertama kali kita menguji kondisi, kita mendapat nilai 0. Jadi kita tidak akan melakukan perjalanan melalui loop, jadi kita tidak akan mencoba untuk mengeksekusi pernyataan bermasalah k=k++sama sekali.
Dengan kata lain, dalam loop khusus ini, meskipun saya mengatakan bahwa "ada dua hal yang terjadi", ternyata hal 1 terjadi satu kali, tetapi hal 2 terjadi nol kali.
Bagaimanapun, saya harap sekarang cukup jelas mengapa alasan yang buruk untuk program ini akhirnya mencetak -1 sebagai nilai akhir dari k. Biasanya, saya tidak suka menjawab pertanyaan kuis seperti ini - rasanya seperti curang - tetapi dalam kasus ini, karena saya sangat tidak setuju dengan seluruh poin latihan, saya tidak keberatan.