Itu tidak terdefinisi karena ia memodifikasi x
dua kali antara titik urutan. Standar mengatakan itu tidak terdefinisi, oleh karena itu tidak terdefinisi.
Setahu saya itu.
Tapi kenapa?
Pemahaman saya adalah bahwa melarang hal ini memungkinkan kompiler untuk mengoptimalkan dengan lebih baik. Ini bisa masuk akal ketika C ditemukan, tetapi sekarang sepertinya argumen yang lemah.
Jika kita menemukan kembali C hari ini, apakah kita akan melakukannya dengan cara ini, atau dapatkah itu dilakukan dengan lebih baik?
Atau mungkin ada masalah yang lebih dalam, yang membuatnya sulit untuk mendefinisikan aturan yang konsisten untuk ekspresi seperti itu, jadi yang terbaik adalah melarangnya?
Jadi misalkan kita menciptakan kembali C hari ini. Saya ingin menyarankan aturan sederhana untuk ekspresi seperti x=x++
, yang menurut saya bekerja lebih baik daripada aturan yang ada.
Saya ingin mendapatkan pendapat Anda tentang aturan yang disarankan dibandingkan dengan yang ada, atau saran lainnya.
Aturan yang Disarankan:
- Di antara titik-titik urutan, urutan evaluasi tidak ditentukan.
- Efek samping segera terjadi.
Tidak ada perilaku tidak jelas yang terlibat. Ekspresi mengevaluasi nilai ini atau itu, tetapi pasti tidak akan memformat hard disk Anda (anehnya, saya belum pernah melihat implementasi di mana x=x++
memformat hard disk).
Contoh Ekspresi
x=x++
- Didefinisikan dengan baik, tidak berubahx
.
Pertama,x
ditambahkan (segera ketikax++
dievaluasi), lalu nilai lamanya disimpanx
.x++ + ++x
- Peningkatanx
dua kali, dievaluasi menjadi2*x+2
.
Meskipun kedua sisi dapat dievaluasi terlebih dahulu, hasilnya adalahx + (x+2)
(sisi kiri terlebih dahulu) atau(x+1) + (x+1)
(sisi kanan terlebih dahulu).x = x + (x=3)
- Tidak ditentukan,x
diatur ke salah satux+3
atau6
.
Jika sisi kanan dievaluasi dulu, itux+3
. Mungkin jugax=3
dievaluasi dulu, jadi begitu3+3
. Dalam kedua kasus,x=3
penugasan terjadi segera ketikax=3
dievaluasi, sehingga nilai yang disimpan ditimpa oleh penugasan lain.x+=(x=3)
- Didefinisikan dengan baik, setx
ke 6.
Anda bisa berpendapat bahwa ini hanya singkatan untuk ungkapan di atas.
Tetapi saya akan mengatakan bahwa itu+=
harus dieksekusi setelahx=3
, dan tidak dalam dua bagian (bacax
, evaluasix=3
, tambahkan, dan simpan nilai baru).
Apa Keuntungannya?
Beberapa komentar mengangkat poin bagus ini.
Saya tentu tidak berpikir ekspresi seperti x=x++
harus digunakan dalam kode normal apa pun.
Sebenarnya, aku jauh lebih ketat dari itu - saya pikir penggunaan hanya baik untuk x++
sebagai x++;
saja.
Namun, saya pikir aturan bahasanya harus sesederhana mungkin. Kalau tidak, programmer tidak akan memahaminya. aturan yang melarang mengubah variabel dua kali antara titik urut tentu saja merupakan aturan yang kebanyakan programmer tidak mengerti.
Aturan yang sangat mendasar adalah ini:
Jika A valid, dan B valid, dan digabungkan dengan cara yang valid, hasilnya valid.
x
adalah nilai-L yang valid, x++
apakah ekspresi yang valid, dan =
apakah cara yang valid untuk menggabungkan nilai-L dan ekspresi, jadi mengapa x=x++
tidak sah?
Standar C membuat pengecualian di sini, dan pengecualian ini memperumit aturan. Anda dapat mencari stackoverflow.com dan melihat seberapa banyak pengecualian ini membingungkan orang.
Jadi saya katakan - singkirkan kebingungan ini.
=== Ringkasan Jawaban ===
Kenapa melakukan itu?
Saya mencoba menjelaskan pada bagian di atas - Saya ingin aturan C menjadi sederhana.Potensi untuk pengoptimalan:
Ini memang membutuhkan kebebasan dari kompiler, tetapi saya tidak melihat apa pun yang meyakinkan saya bahwa itu mungkin signifikan.
Sebagian besar optimasi masih bisa dilakukan. Misalnya,a=3;b=5;
dapat dipesan ulang, meskipun standar menentukan pesanan. Ekspresi sepertia=b[i++]
masih dapat dioptimalkan dengan cara yang sama.Anda tidak dapat mengubah standar yang ada.
Saya akui, saya tidak bisa. Saya tidak pernah berpikir saya benar-benar dapat melanjutkan dan mengubah standar dan kompiler. Saya hanya ingin berpikir jika segala sesuatunya dapat dilakukan secara berbeda.
x
untuk dirinya sendiri, dan jika Anda ingin menambahx
Anda bisa mengatakanx++;
- tidak perlu untuk tugas itu. Saya akan mengatakannya tidak boleh didefinisikan hanya karena akan sulit untuk mengingat apa yang seharusnya terjadi.