Apa itu "hubungan arus pendek" dalam bahasa seperti C?

14

Saya telah mendengar istilah "hubungan arus pendek" yang digunakan dalam C, C ++, C #, Java, dan banyak lainnya. Apa artinya ini dan dalam skenario apa yang akan digunakan?

fasil
sumber
6
Ada Artikel Wikipedia tentang konsep: en.wikipedia.org/wiki/Short-circuit_evaluation Ini adalah pengoptimalan dalam evaluasi &&operator.
wirrbel
1
@ Wirrbel Saya percaya itu berlaku ||juga ... setidaknya seharusnya.
Radu Murzea
1
@RaduMurzea Memang. Kontras ||dan &&ke &dan |untuk melihat perbedaan yang halus. Mintalah program sederhana untuk mengevaluasi 1 || printf("yay");vs 0 || printf("yay");dan 1 | printf("yay");vs 0 | printf("yay");untuk melihat perbedaannya
wirrbel

Jawaban:

35

Hubungan arus pendek dalam C adalah ketika operator logis tidak mengevaluasi semua argumennya.

Ambil contoh dan &&, sudah cukup jelas bahwa 0 && WhoCaresitu akan salah, apa pun WhoCaresitu. Karena itu, C hanya melewatkan evaluasi WhoCares. Sama berlaku untuk 1 || WhoCares, itu akan selalu benar. Karena itu, kita dapat menulis kode seperti

CanFireMissiles && FireMissiles()

Dengan cara ini kami menghindari melakukan beberapa operasi yang tidak mungkin dilakukan. Jika kita tidak dapat menembakkan rudal, kita tentu tidak ingin mencobanya. Ini biasa digunakan dengan pointer, terutama pointer file.

 bool isN(int* ptr, int n){
     return ptr && *ptr == n;
 }

Ini memainkan banyak cara berguna lainnya untuk menghindari komputasi yang tidak perlu

 isFileReady() || getFileReady()

Ini menghindari melakukan pekerjaan ekstra jika kita tidak perlu.

Daniel Gratzer
sumber
1
Kapan saja, jika saya telah menjawab pertanyaan Anda, Anda dapat mencentang kotak di sebelahnya untuk menandai pertanyaan Anda sebagai dijawab
Daniel Gratzer
7
Saya tidak suka CanFireMissiles && FireMissiles(), karena itu membuat saya curiga Anda menyalahgunakan hubungan arus pendek untuk memicu efek samping. Saya merasa seperti Anda menyembunyikan tindakan dalam kondisi. Kode seperti itu lebih baik ditulis sebagai if(CanFireMissiles){FireMissiles();}atau if(CanFireMissles){didFireMissiles = TryFireMissiles(); if(didFireMissiles){...}}.
Brian
2
Saya berpendapat bahwa satu-satunya gunanya menyembunyikan efek samping. Biasanya bukan jenis "Blowing sebuah kota" tetapi hal-hal seperti mendereferensi pointer atau menggunakan sumber daya sistem juga dilakukan dengan cara ini dalam C cukup sering. Lihat halaman wikipedia, seluruh bagian yang digunakan adalah "Menyembunyikan efek samping"
Daniel Gratzer
2
@ jozefg Anda juga dapat menggunakannya untuk mencegah melakukan operasi yang mahal seperti IsInCache(value) || IsInDatabase(value), di mana IsInDatabase membutuhkan waktu (terutama jika menggunakan perangkat seluler dan latensi jaringan merupakan masalah).
mgw854
4

"Hubungan pendek" biasanya mengacu pada " Evaluasi Hubungan Singkat " yang merupakan konsep umum, bukan hanya spesifik C.

Evaluasi operator Boolean dari kiri ke kanan, sehingga istilah apa pun yang akan membuat istilah lain yang tidak perlu berguna. Jadi Anda mungkin memeriksa kondisi yang mengecualikan kondisi lain di kemudian hari, sehingga memungkinkan evaluasi parsial dari operasi logis daripada mengevaluasi semuanya.

Contoh:

while((x && y) == 1) {
    //This bit will not execute if x is 0 or y is 0 but y won't even be 
    //evaluated due to short circuit evaluation if x is 0.
}

Contoh yang lebih kompleks:

if((a || b || c || d || e || f || g || h || i || j || k) == 1) {
    /* If any of these are equal to 1 the whole expression is equal to 1,
     * thus doesn't it make sense to short circuit evaluate this?
     * Saves a bunch of time.
     */
}
Insinyur Dunia
sumber
8
Hubungan arus pendek lebih sedikit tentang menghemat waktu tetapi lebih banyak tentang tidak dievaluasi. Suatu fungsi yang tidak dievaluasi juga tidak akan memiliki efek samping yang akan dievaluasi.
Pieter B
Anda tahu, == 0ini bukan hanya tidak perlu, tetapi mungkin malah membingungkan sebagian orang.
Deduplicator
3

Evaluasi ciruit singkat dapat menyebabkan beberapa bagian dari suatu kondisi tidak dievaluasi.

Sebagai contoh:

if (true || f()) { ... }

tidak akan exectue f.

jujur
sumber