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.

OperatorNamaHasil
&&ANDtrue hanya bila keduanya true
||ORtrue bila minimal satu operand true
!NOTmembalik: !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”.

cpp
#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:

text
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 = false

Mari kita baca buktinya baris demi baris:

  1. Kasus 1 (cekUmur(15) && cekPunyaSim(true)): hanya cekUmur yang dievaluasi. Karena hasilnya false, operator && sudah tahu keseluruhan ekspresi pasti false, sehingga cekPunyaSim tidak pernah dipanggil — tandanya tidak muncul di output.
  2. Kasus 2: kini umurnya 19, penanda cekUmur menghasilkan true, sehingga compiler lanjut mengevaluasi sisi kanan. Kedua penanda berbunyi dan hasilnya true.
  3. Kasus 3 (cekMember(true) || cekPromo(false)): kebalikannya terjadi pada ||. Sisi kiri sudah true, sehingga cekPromo dilewati; hasil tetap true.
  4. Kasus 4: sisi kiri false tidak menentukan hasil ||, jadi kedua sisi dievaluasi dan hasilnya false.
  5. !serverAktif: operator ! membalik false menjadi true tanpa menyentuh isi variabelnya.
  6. Dua baris terakhir: && lebih kuat dari ||, sehingga a || (b && c) bernilai true, sementara kurung eksplisit pada (a || b) && c mengubah urutan dan hasilnya false.

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.