Operator logika menggabungkan beberapa nilai bool menjadi satu keputusan: && (AND) menuntut keduanya benar, || (OR) cukup salah satunya benar, dan ! (NOT) membalik nilai. Tiga operator ini adalah inti dari kondisi program — pada Section Control Flow nanti, hampir setiap if yang kita tulis memakai salah satunya. Ada satu perilaku penting yang membedakan mereka dari operator aritmetika: short-circuit evaluation, yaitu sisi kanan ekspresi bisa dilewati sepenuhnya bila sisi kiri sudah menentukan hasil. Pada Chapter ini kita membuktikannya dengan std::cout di dalam ekspresi, sehingga urutan evaluasi terlihat nyata di output.
Tiga Operator Logika #
Tabel berikut merangkum perilaku ketiganya; nilai operand diambil dari hasil operator perbandingan pada Chapter sebelumnya.
| Operator | Nama | Hasil |
|---|---|---|
&& | AND | true hanya bila keduanya true |
|| | OR | true bila minimal satu operand true |
! | NOT | membalik: !true menjadi false |
Short-Circuit Evaluation: Bukti dari Output #
Cara paling jelas melihat short-circuit adalah memakai fungsi kecil yang mencetak tanda setiap kali ia benar-benar dipanggil. Fungsi semacam ini sederhana: menerima parameter, mencetak satu baris, lalu mengembalikan bool. Pemahaman fungsi mendalam kita tunda sampai Section Fungsi; untuk saat ini cukup baca fungsi tersebut sebagai “penanda yang berbunyi saat dievaluasi”.
#include <iostream>
// Fungsi penanda: mencetak saat benar-benar dievaluasi, lalu mengembalikan bool
bool cekUmur(int umur) {
std::cout << " -> cekUmur dievaluasi\n";
return umur >= 17;
}
bool cekPunyaSim(bool punya) {
std::cout << " -> cekPunyaSim dievaluasi\n";
return punya;
}
bool cekMember(bool status) {
std::cout << " -> cekMember dievaluasi\n";
return status;
}
bool cekPromo(bool status) {
std::cout << " -> cekPromo dievaluasi\n";
return status;
}
int main() {
std::cout << std::boolalpha;
// Short-circuit pada &&: sisi kanan dilewati bila sisi kiri false
std::cout << "Kasus 1: umur 15, punya SIM true\n";
bool bolehBerkendara = cekUmur(15) && cekPunyaSim(true);
std::cout << "bolehBerkendara = " << bolehBerkendara << "\n\n";
std::cout << "Kasus 2: umur 19, punya SIM true\n";
bolehBerkendara = cekUmur(19) && cekPunyaSim(true);
std::cout << "bolehBerkendara = " << bolehBerkendara << "\n\n";
// Short-circuit pada ||: sisi kanan dilewati bila sisi kiri true
std::cout << "Kasus 3: member true, promo false\n";
bool dapatDiskon = cekMember(true) || cekPromo(false);
std::cout << "dapatDiskon = " << dapatDiskon << "\n\n";
std::cout << "Kasus 4: member false, promo false\n";
dapatDiskon = cekMember(false) || cekPromo(false);
std::cout << "dapatDiskon = " << dapatDiskon << "\n\n";
// Operator ! membalik nilai bool
bool serverAktif = false;
std::cout << "serverAktif = " << serverAktif << "\n";
std::cout << "!serverAktif = " << !serverAktif << "\n\n";
// Precedence: ! lalu && lalu ||; kurung mengubah urutan
bool a = true;
bool b = false;
bool c = false;
std::cout << "a || (b && c) = " << (a || (b && c)) << "\n";
std::cout << "(a || b) && c = " << ((a || b) && c) << "\n";
return 0;
}Output yang Dihasilkan:
Kasus 1: umur 15, punya SIM true
-> cekUmur dievaluasi
bolehBerkendara = false
Kasus 2: umur 19, punya SIM true
-> cekUmur dievaluasi
-> cekPunyaSim dievaluasi
bolehBerkendara = true
Kasus 3: member true, promo false
-> cekMember dievaluasi
dapatDiskon = true
Kasus 4: member false, promo false
-> cekMember dievaluasi
-> cekPromo dievaluasi
dapatDiskon = false
serverAktif = false
!serverAktif = true
a || (b && c) = true
(a || b) && c = falseMari kita baca buktinya baris demi baris:
- Kasus 1 (
cekUmur(15) && cekPunyaSim(true)): hanyacekUmuryang dievaluasi. Karena hasilnyafalse, operator&&sudah tahu keseluruhan ekspresi pastifalse, sehinggacekPunyaSimtidak pernah dipanggil — tandanya tidak muncul di output. - Kasus 2: kini umurnya
19, penandacekUmurmenghasilkantrue, sehingga compiler lanjut mengevaluasi sisi kanan. Kedua penanda berbunyi dan hasilnyatrue. - Kasus 3 (
cekMember(true) || cekPromo(false)): kebalikannya terjadi pada||. Sisi kiri sudahtrue, sehinggacekPromodilewati; hasil tetaptrue. - Kasus 4: sisi kiri
falsetidak menentukan hasil||, jadi kedua sisi dievaluasi dan hasilnyafalse. !serverAktif: operator!membalikfalsemenjaditruetanpa menyentuh isi variabelnya.- Dua baris terakhir:
&&lebih kuat dari||, sehinggaa || (b && c)bernilaitrue, sementara kurung eksplisit pada(a || b) && cmengubah urutan dan hasilnyafalse.
Urutan output ini pasti, bukan kebetulan: standar C++ menjamin && dan || selalu mengevaluasi operand kiri lebih dulu, lalu (bila perlu) operand kanan. Jaminan ini berbeda dari operator aritmetika seperti +, yang urutan evaluasi operandnya tidak dijamin — kita kembali ke topik itu pada Chapter Precedence dan Associativity.
Mengapa Short-Circuit Berguna #
Short-circuit bukan sekadar penghematan; ia adalah alat menjaga keamanan ekspresi. Pola umumnya: letakkan pengecekan yang paling murah atau paling menentukan di kiri, sehingga pengecekan yang berisiko di kanan tidak pernah berjalan bila tidak perlu. Contoh klasiknya adalah memastikan nilai pembagi tidak nol sebelum melakukan pembagian pada ekspresi yang sama.
Urutan Kekuatan: ! lalu && lalu || #
Ketika ketiga operator bercampur dalam satu ekspresi, ! mengikat paling kuat, disusul &&, lalu || yang paling lemah. Ekspresi !a && b || c oleh compiler dibaca sebagai ((!a) && b) || c. Bila ragu, tulis kurungnya: kode dengan kurung eksplisit selalu lebih mudah dibaca dan bebas dari salah tafsir. GCC bahkan aktif memberi peringatan -Wparentheses bila kita mencampur && dan || tanpa kurung — sinyal bahwa pola tersebut rawan disalahpahami.
Dengan &&, ||, dan ! di tangan, kita sudah bisa membentuk kondisi sembilanan. Masih ada satu pasang operator yang bekerja pada bool dan angka dengan cara unik: ++ dan --, yang menaikkan atau menurunkan nilai satu langkah — topik Chapter berikutnya.