Apakah standar ANSI mengamanatkan operator logis untuk dihubung pendek, baik dalam C atau C ++?
Saya bingung karena saya ingat buku K&R yang mengatakan kode Anda tidak boleh bergantung pada operasi yang dihubung pendek ini, karena mungkin saja tidak. Bisakah seseorang tolong tunjukkan di mana dalam standar dikatakan ops logika selalu mengalami hubungan pendek? Saya sebagian besar tertarik pada C ++, jawaban juga untuk C akan lebih bagus.
Saya juga ingat membaca (tidak ingat di mana) bahwa urutan evaluasi tidak ditentukan secara ketat, jadi kode Anda tidak boleh bergantung atau menganggap fungsi dalam ekspresi akan dieksekusi dalam urutan tertentu: pada akhir pernyataan semua fungsi yang direferensikan akan dipanggil, tetapi kompiler memiliki kebebasan dalam memilih urutan yang paling efisien.
Apakah standar menunjukkan urutan evaluasi ungkapan ini?
if( functionA() && functionB() && functionC() ) cout<<"Hello world";
sumber
Jawaban:
Ya, hubungan arus pendek dan urutan evaluasi diperlukan untuk operator
||
dan&&
dalam standar C dan C ++.Standar C ++ mengatakan (harus ada klausa yang setara dalam standar C):
Di C ++ ada jebakan tambahan: korsleting TIDAK berlaku untuk tipe yang membebani operator
||
dan&&
.Biasanya tidak disarankan untuk membebani operator ini dalam C ++ kecuali Anda memiliki persyaratan yang sangat spesifik. Anda dapat melakukannya, tetapi itu mungkin melanggar perilaku yang diharapkan dalam kode orang lain, terutama jika operator ini digunakan secara tidak langsung melalui instantiating templat dengan tipe overload operator ini.
sumber
Evaluasi hubung singkat, dan urutan evaluasi, adalah standar semantik yang diamanatkan dalam C dan C ++.
Jika tidak, kode seperti ini tidak akan menjadi ungkapan yang umum
Bagian 6.5.13 Logical operator AND dari spesifikasi C99 (PDF link) mengatakan
Demikian pula, bagian 6.5.14 Logika ATAU operator kata
Kata-kata yang mirip dapat ditemukan dalam standar C ++, periksa bagian 5.14 dalam draft draft ini . Seperti yang dicatat oleh catur dalam jawaban lain, jika Anda mengabaikan && atau ||, maka kedua operan harus dievaluasi karena menjadi panggilan fungsi biasa.
sumber
Ya, itu mengamanatkan (urutan evaluasi dan hubungan pendek). Dalam contoh Anda jika semua fungsi mengembalikan true, urutan panggilan secara ketat dari functionA lalu functionB dan kemudian functionC. Digunakan untuk seperti ini
Sama untuk operator koma:
Salah satu kata antara kiri dan operan kanan
&&
,||
,,
dan antara pertama dan kedua / operan ketiga?:
(operator kondisional) adalah "titik urutan". Setiap efek samping dievaluasi sepenuhnya sebelum titik itu. Jadi, ini aman:Perhatikan bahwa operator koma tidak perlu bingung dengan koma sintaksis yang digunakan untuk memisahkan hal-hal:
Standar C ++ mengatakan
5.14/1
:Dan di
5.15/1
:Dikatakan untuk keduanya di sebelah:
Selain itu,
1.9/18
katasumber
Langsung dari K&R tua yang baik:
sumber
Berhati-hatilah.
Untuk tipe fundamental, ini adalah operator pintasan.
Tetapi jika Anda mendefinisikan operator ini untuk kelas Anda sendiri atau tipe enumerasi mereka bukan jalan pintas. Karena perbedaan semantik ini dalam penggunaannya dalam keadaan yang berbeda ini, disarankan agar Anda tidak mendefinisikan operator ini.
Untuk
operator &&
danoperator ||
untuk tipe dasar urutan evaluasi dibiarkan dari kanan (jika tidak, pemotongan pendek akan sulit :-) Tetapi untuk operator kelebihan beban yang Anda tetapkan, ini pada dasarnya adalah sintaksis gula untuk mendefinisikan metode dan dengan demikian urutan evaluasi parameter adalah tidak terdefinisi.sumber
Pertanyaan Anda sampai pada prioritas operator C ++ dan asosiasi. Pada dasarnya, dalam ekspresi dengan beberapa operator dan tanpa tanda kurung, kompiler membangun pohon ekspresi dengan mengikuti aturan-aturan ini.
Untuk didahulukan, ketika Anda memiliki sesuatu seperti
A op1 B op2 C
, Anda dapat mengelompokkan hal-hal sebagai(A op1 B) op2 C
atauA op1 (B op2 C)
. Jikaop1
memiliki prioritas lebih tinggi daripadaop2
, Anda akan mendapatkan ekspresi pertama. Kalau tidak, Anda akan mendapatkan yang kedua.Untuk asosiatif, ketika Anda memiliki sesuatu seperti
A op B op C
, Anda dapat mengelompokkan kembali sebagai(A op B) op C
atauA op (B op C)
. Jikaop
telah meninggalkan asosiasi, kita berakhir dengan ekspresi pertama. Jika asosiasi itu benar, kita berakhir dengan asosiasi kedua. Ini juga berfungsi untuk operator pada tingkat prioritas yang sama.Dalam kasus khusus ini,
&&
memiliki prioritas lebih tinggi daripada||
, sehingga ekspresi akan dievaluasi sebagai(a != "" && it == seqMap.end()) || isEven
.Urutan itu sendiri adalah "kiri-ke-kanan" pada bentuk pohon ekspresi. Jadi pertama-tama kita akan mengevaluasi
a != "" && it == seqMap.end()
. Jika itu benar seluruh ekspresi itu benar, kalau tidak kita pergi keisEven
. Prosedur ini berulang dengan sendirinya di dalam sub-ekspresi kiri saja.Berita menarik, tetapi konsep diutamakan berakar pada notasi matematika. Hal yang sama terjadi di
a*b + c
, di mana*
memiliki prioritas lebih tinggi daripada+
.Bahkan lebih menarik / tidak jelas, untuk ekspresi yang tidak dipalsukan
A1 op1 A2 op2 ... opn-1 An
, di mana semua operator memiliki prioritas yang sama, jumlah pohon ekspresi biner yang dapat kita bentuk diberikan oleh apa yang disebut angka Catalan . Untuk yang besarn
, ini tumbuh sangat cepat. dsumber
Jika Anda mempercayai Wikipedia:
C (bahasa pemrograman)
sumber