Topik ini membahas operator C++ yang membentuk sebuah ekspresi, yaitu kombinasi nilai dan operator yang menghasilkan satu nilai. Cakupannya meliputi operator aritmetika, relasional, logika, bitwise, ternary, serta urutan prioritas yang menentukan urutan perhitungan. Setiap kelompok operator diperagakan dengan program kecil yang keluarannya dapat dihitung ulang dengan tangan.
Operator aritmetika dan pembagian bilangan bulat#
Operator aritmetika menghitung nilai numerik dengan simbol +, -, *, /, dan %. Empat simbol pertama mengikuti kebiasaan matematika, sedangkan % menghasilkan sisa pembagian dan hanya berlaku untuk tipe bilangan bulat. Program berikut menghitung seluruhnya dari dua nilai yang sama, yaitu 17 dan 5.
#include <iostream>
int main() {
int a = 17;
int b = 5;
std::cout << "a + b = " << a + b << "\n";
std::cout << "a - b = " << a - b << "\n";
std::cout << "a * b = " << a * b << "\n";
std::cout << "a / b = " << a / b << "\n"; // pembagian bilangan bulat
std::cout << "a % b = " << a % b << "\n"; // sisa pembagian
std::cout << "a / 2.0 = " << a / 2.0 << "\n";
return 0;
}a + b = 22
a - b = 12
a * b = 85
a / b = 3
a % b = 2
a / 2.0 = 8.5Hasil a / b bernilai 3, bukan 3.4, karena kedua operannya bertipe int. Pembagian bilangan bulat membuang bagian pecahan dari hasilnya. Sebaliknya, a / 2.0 menghasilkan 8.5 karena satu operannya bertipe double dan membuat perhitungan beralih ke pembagian pecahan. Aturan inilah yang sering terlewat ketika rata-rata dihitung dari dua bilangan bulat.
Operator penaikan, penurunan, dan penugasan gabungan#
Operator ++ menaikkan nilai satu, sedangkan -- menurunkan nilai satu, dan keduanya memiliki dua bentuk dengan perilaku berbeda. Bentuk penanda akhiran (postfix) seperti stok++ menghasilkan nilai lama terlebih dahulu, sedangkan bentuk awalan (prefix) seperti ++stok menghasilkan nilai baru. Operator penugasan gabungan seperti +=, -=, *=, dan /= memperbarui variabel dengan satu operasi aritmetika dalam satu tulisan. Program berikut memeragakan semuanya pada satu variabel.
#include <iostream>
int main() {
int stok = 10;
std::cout << "stok = " << stok << "\n";
std::cout << "stok++ = " << stok++ << " (nilai lama)\n";
std::cout << "stok kini = " << stok << "\n";
std::cout << "++stok = " << ++stok << " (nilai baru)\n";
stok -= 3;
std::cout << "stok -= 3 = " << stok << "\n";
stok *= 2;
std::cout << "stok *= 2 = " << stok << "\n";
return 0;
}stok = 10
stok++ = 10 (nilai lama)
stok kini = 11
++stok = 12 (nilai baru)
stok -= 3 = 9
stok *= 2 = 18Baris stok++ mencetak 10 lalu menyimpan 11, sedangkan ++stok langsung menyimpan dan mencetak 12. Nilai lama yang tampil pada baris stok++ bukan sisa perhitungan sebelumnya, melainkan hasil ekspresinya. Bentuk penugasan gabungan menghemat penulisan nama variabel dua kali, dan maknanya identik dengan stok = stok - 3 pada kasus tersebut. Operator -- berperilaku simetris dengan ++, yaitu stok-- menghasilkan nilai lama dan --stok menghasilkan nilai baru. Bagian yang perlu dijaga adalah posisi tandanya, karena hasil ekspresi berubah bergantung posisi tersebut.
Tanda hasil pada pembagian dan modulo negatif#
Pada operan negatif, C++ menetapkan hasil pembagian bilangan bulat dibulatkan menuju nol (truncation), dan sisa pembagian mengikuti tanda bilangan yang dibagi. Aturan ini ditetapkan sejak C++11 sehingga hasilnya sama di semua compiler modern. Program berikut menguji ketiga kombinasi tandanya.
#include <iostream>
int main() {
std::cout << "-7 / 2 = " << -7 / 2 << "\n";
std::cout << "-7 % 2 = " << -7 % 2 << "\n";
std::cout << "7 % -2 = " << 7 % -2 << "\n";
return 0;
}-7 / 2 = -3
-7 % 2 = -1
7 % -2 = 1Pembagian -7 / 2 menghasilkan -3 dan bukan -4, karena pembulatan menuju nol membuang pecahan tanpa menjauh dari nol. Sisa -7 % 2 bernilai -1 yang mengikuti tanda -7, sedangkan 7 % -2 bernilai 1 yang mengikuti tanda 7. Aturan ini penting ketika nilai yang dihitung bisa negatif, misalnya posisi indeks yang melompat mundur, karena asumsi sisa selalu positif akan menghasilkan indeks di luar rentang.
Operator relasional dan logika#
Operator relasional membandingkan dua nilai dan menghasilkan bool, yaitu true atau false, yang tercetak sebagai 1 atau 0. Kelompoknya terdiri atas ==, !=, <, <=, >, dan >=. Operator logika && (dan), || (atau), serta ! (negasi) menggabungkan nilai-nilai bool tersebut menjadi satu keputusan.
#include <iostream>
bool cekStok(int kode) {
std::cout << "cekStok(" << kode << ") dipanggil\n";
return kode > 0;
}
int main() {
bool habisDikurangi = cekStok(-1) && cekStok(5); // cekStok(5) tidak dieksekusi
bool tersedia = cekStok(3) || cekStok(-2); // cekStok(-2) tidak dieksekusi
std::cout << "habisDikurangi = " << habisDikurangi << ", tersedia = " << tersedia << "\n";
return 0;
}cekStok(-1) dipanggil
cekStok(3) dipanggil
habisDikurangi = 0, tersedia = 1Keluaran membuktikan sifat short-circuit evaluation, yaitu evaluasi yang berhenti segera setelah hasilnya pasti. Untuk &&, apabila operan kiri bernilai false, hasilnya pasti false sehingga operan kanan tidak dieksekusi. Untuk ||, berlaku kebalikannya, yaitu nilai true di kiri menghentikan evaluasi. Sifat ini bukan sekadar penghematan, melainkan fondasi pola seperti pemeriksaan pointer sebelum dipakai.
Operator bitwise#
Operator bitwise memanipulasi nilai pada tingkat bit, dan kelompoknya terdiri atas & (AND), | (OR), ^ (XOR), << (geser kiri), serta >> (geser kanan). Pada contoh berikut, nilai 12 dan 10 ditulis dalam biner sebagai 1100 dan 1010 sehingga hasil tiap operasi dapat dihitung langsung per bit.
#include <iostream>
int main() {
unsigned int x = 12; // biner: 1100
unsigned int y = 10; // biner: 1010
std::cout << "x & y = " << (x & y) << "\n";
std::cout << "x | y = " << (x | y) << "\n";
std::cout << "x ^ y = " << (x ^ y) << "\n";
std::cout << "x << 2 = " << (x << 2) << "\n";
std::cout << "x >> 1 = " << (x >> 1) << "\n";
return 0;
}x & y = 8
x | y = 14
x ^ y = 6
x << 2 = 48
x >> 1 = 6Perhitungannya sederhana, misalnya 1100 AND 1010 menghasilkan 1000 yang bernilai 8. Pergeseran kiri dua langkah menggandakan nilai dua kali menjadi 48, sedangkan pergeseran kanan satu langkah membaginya dengan dua menjadi 6. Perhatikan tanda kurung pada setiap ekspresi. Operator << milik stream berprioritas lebih tinggi daripada operator bitwise, sehingga tanpa tanda kurung ekspresi seperti std::cout << x & y dibaca sebagai (std::cout << x) & y dan ditolak compiler.
Operator ternary dan urutan prioritas#
Operator ternary kondisi ? nilaiJikaTrue : nilaiJikaFalse memilih salah satu dari dua nilai berdasarkan satu kondisi, sehingga cocok untuk penentuan nilai alih-alih percabangan penuh. Urutan perhitungan sebuah ekspresi ditentukan oleh tabel prioritas (precedence) compiler, dan tanda kurung tetap menjadi cara paling jelas untuk memaksakan urutan yang diinginkan.
#include <iostream>
#include <string>
int main() {
int nilai = 86;
std::string predikat = (nilai >= 80) ? "sangat baik" : "baik";
std::cout << "predikat = " << predikat << "\n";
std::cout << "2 + 3 * 4 = " << 2 + 3 * 4 << "\n";
std::cout << "(2 + 3) * 4 = " << (2 + 3) * 4 << "\n";
std::cout << "nilai >= 80 = " << (nilai >= 80) << "\n";
return 0;
}predikat = sangat baik
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
nilai >= 80 = 1Ekspresi 2 + 3 * 4 menghasilkan 14 karena * memiliki prioritas lebih tinggi daripada +, sedangkan penambahan tanda kurung mengubah hasilnya menjadi 20. Tabel berikut menyusun kelompok operator yang dibahas, dari prioritas tertinggi di atas ke terendah di bawah.
| Prioritas | Kelompok operator | Contoh |
|---|---|---|
| Tertinggi | Panggilan dan kurung | (), [] |
| Tinggi | Unary | !, -x, ++, -- |
| Menengah | Aritmetika | *, /, %, lalu +, - |
| Menengah | Pergeseran | <<, >> |
| Rendah | Relasional | <, <=, >, >=, lalu ==, != |
| Lebih rendah | Logika | &&, lalu ` |
| Terendah | Ternary dan penugasan | ?:, =, += |
Kesalahan umum#
Kesalahan-kesalahan berikut paling sering muncul ketika ekspresi mulai digabung-gabung.
- Menulis
=alih-alih==pada kondisi. Pernyataanif (jumlah = 0)menugaskan nilai 0 kejumlahlalu menilai hasilnya sebagaifalse, sehingga percabangan tidak pernah berjalan seperti harapan. Perbaikannya menggunakan==untuk perbandingan. - Mengharapkan hasil pecahan dari pembagian bilangan bulat. Ekspresi
7 / 2bernilai3karena kedua operannya bulat, dan perbaikannya adalah membuat salah satu operannya bertipe pecahan. - Melupakan tanda kurung pada gabungan bitwise dan perbandingan. Ekspresi
x & mask == 0dibaca compiler sebagaix & (mask == 0), karena==berprioritas lebih tinggi daripada&, sedangkan niat aslinya adalah(x & mask) == 0. - Menggunakan
&dan|alih-alih&&dan||pada kondisi. Keduanya sah secara sintaks, tetapi tidak mengevaluasi secara short-circuit, sehingga operan kanan tetap dieksekusi walaupun hasilnya sudah pasti. Pola pemeriksaan pointer menjadi tidak aman bila ditulis dengan&, karena sisi kanan tetap dieksekusi meskipun pointer sedang kosong. - Membandingkan bilangan pecahan dengan
==. Ekspresi0.1 + 0.2 == 0.3bernilaifalsekarena representasi biner kedua sisi tidak persis sama, meskipun keluaran yang dicetak tampak sama. Perbaikannya membandingkan selisih dengan batas kecil, misalnyastd::abs(0.1 + 0.2 - 0.3) < 0.000001dari header<cmath>.
Ringkasan#
- Operator aritmetika pada dua operan bulat menghasilkan nilai bulat, sehingga
/membuang pecahan dan%menghasilkan sisa pembagian. - Operator relasional menghasilkan
bool, sedangkan&&dan||mengevaluasi dengan sifat short-circuit sehingga operan kanan bisa saja tidak dieksekusi. - Operator bitwise bekerja per bit, dan pergeseran kiri menggandakan nilai bilangan bulat tak bertanda, sedangkan pergeseran kanan membaginya.
- Urutan perhitungan ekspresi mengikuti tabel prioritas, dan tanda kurung menjadi cara paling jelas untuk menegaskan niat.
Referensi#
- Operator precedence — cppreference — Tabel lengkap prioritas dan asosiativitas seluruh operator C++.
- Arithmetic operators — cppreference — Aturan pembagian bilangan bulat dan sisa pembagian beserta tandanya.
- Increment/decrement operators — cppreference — Perbedaan bentuk awalan dan akhiran pada operator ++ dan –.
- Logical operators — cppreference — Aturan evaluasi operator logika beserta sifat short-circuit.
- Arithmetic operators — LearnCpp — Pembahasan operator aritmetika termasuk pembagian bilangan bulat.
- Logical operators — LearnCpp
— Penjelasan
&&,||, dan!beserta evaluasinya. - Bit manipulation with bitwise operators and bit masks — LearnCpp — Panduan manipulasi bit dengan operator bitwise.
- The conditional operator — LearnCpp — Pembahasan operator ternary dan kapan ia dipakai.