Operator di C memiliki aturan precedence (kedudukan) dan associativity (arah evaluasi) yang menentukan urutan operasi pada ekspresi kompleks. Saat kita menulis a + b * c, compiler memahami ini sebagai a + (b * c) karena * memiliki precedence lebih tinggi daripada +. Bab ini menyediakan tabel referensi lengkap untuk semua operator C beserta contoh penggunaan dan jebakan yang sering kita temui.
Daftar Operator Berdasarkan Precedence #
Tabel berikut diurutkan dari precedence tertinggi (atas) ke terendah (bawah). Operator pada baris yang sama memiliki precedence sama, dan associativity menentukan urutan evaluasi jika beberapa operator precedence sama muncul berurutan.
| Precedence | Operator | Nama | Associativity | Contoh | Hasil (a=10, b=3) |
|---|---|---|---|---|---|
| 1 | () | Pemanggilan fungsi / grouping | L ke R | (a + b) | 13 |
| 1 | [] | Index array | L ke R | arr[2] | elemen ke-3 |
| 1 | . | Akses member struct | L ke R | obj.x | field x |
| 1 | -> | Akses member via pointer | L ke R | ptr->x | field x |
| 1 | (post)++ | Post-increment | L ke R | a++ | 10 (a jadi 11) |
| 1 | (post)-- | Post-decrement | L ke R | a-- | 10 (a jadi 9) |
| 2 | ++(pre) | Pre-increment | R ke L | ++a | 11 |
| 2 | --(pre) | Pre-decrement | R ke L | --a | 9 |
| 2 | + (unary) | Unary plus | R ke L | +a | 10 |
| 2 | - (unary) | Unary minus | R ke L | -a | -10 |
| 2 | ! | Logical NOT | R ke L | !a | 0 |
| 2 | ~ | Bitwise NOT | R ke L | ~a | -11 |
| 2 | (type) | Cast | R ke L | (double)a | 10.0 |
| 2 | * (deref) | Dereference pointer | R ke L | *ptr | nilai di ptr |
| 2 | & (addr) | Address-of | R ke L | &a | alamat a |
| 2 | sizeof | Ukuran tipe/objek | R ke L | sizeof(int) | 4 |
| 2 | _Alignof | Alignment requirement | R ke L | _Alignof(int) | 4 |
| 3 | * / / / % | Perkalian, pembagian, modulo | L ke R | a * b, a % b | 30, 1 |
| 4 | + / - (biner) | Penjumlahan, pengurangan | L ke R | a + b, a - b | 13, 7 |
| 5 | << / >> | Bitwise shift | L ke R | a << 2, a >> 1 | 40, 5 |
| 6 | < / <= / > / >= | Relational | L ke R | a > b | 1 |
| 7 | == / != | Persamaan | L ke R | a == b | 0 |
| 8 | & (bitwise) | Bitwise AND | L ke R | a & b | 2 |
| 9 | ^ | Bitwise XOR | L ke R | a ^ b | 9 |
| 10 | ` | ` | Bitwise OR | L ke R | `a |
| 11 | && | Logical AND | L ke R | (a > 0) && (b > 0) | 1 |
| 12 | ` | ` | Logical OR | L ke R | |
| 13 | ?: | Ternary kondisional | R ke L | (a > b) ? a : b | 10 |
| 14 | = | Assignment | R ke L | a = 5 | 5 |
| 14 | += -= *= /= %= | Compound aritmetika | R ke L | a += 5 | 15 |
| 14 | <<= >>= | Compound shift | R ke L | a <<= 2 | 40 |
| 14 | &= ^= ` | =` | Compound bitwise | R ke L | a &= 0xF |
| 15 | , | Comma | L ke R | (x=1, y=2) | 2 |
Aritmetika, Bitwise, dan Logika #
Kode berikut mendemonstrasikan seluruh operator aritmetika, bitwise, logika, assignment gabungan, increment, ternary, comma, dan sizeof dalam satu program. Output pada setiap baris dicantumkan sebagai komentar untuk verifikasi.
/* File: op1.c - Demonstrasi operator C */
#include <stdio.h>
static int step(int *p) { *p += 1; return *p; }
int main(void) {
int a = 10, b = 3, c = 5;
/* Aritmetika */
printf("a + b = %d\n", a + b); /* 13 */
printf("a - b = %d\n", a - b); /* 7 */
printf("a * b = %d\n", a * b); /* 30 */
printf("a / b = %d\n", a / b); /* 3 (integer division) */
printf("a %% b = %d\n", a % b); /* 1 (modulo) */
printf("-a = %d\n", -a); /* -10 (unary minus) */
/* Bitwise */
printf("a & b = %d\n", a & b); /* 2 */
printf("a | b = %d\n", a | b); /* 11 */
printf("a ^ b = %d\n", a ^ b); /* 9 */
printf("~a = %d\n", ~a); /* -11 */
printf("a << 2 = %d\n", a << 2); /* 40 */
printf("a >> 1 = %d\n", a >> 1); /* 5 */
/* Perbandingan dan logika */
printf("a > b : %d\n", a > b); /* 1 */
printf("(a > b) && (c > 0) : %d\n", (a > b) && (c > 0)); /* 1 */
printf("(a < b) || (c > 0) : %d\n", (a < b) || (c > 0)); /* 1 */
printf("! (a > b) : %d\n", !(a > b)); /* 0 */
/* Assignment gabungan */
int x = 100;
x += 5; printf("x += 5 -> %d\n", x); /* 105 */
x <<= 3; printf("x <<= 3 -> %d\n", x); /* 24 (setelah x=3 dari %/) */
x &= 0xF; printf("x &= 0xF -> %d\n", x);/* 8 */
/* Increment / decrement */
int y = 7;
int post = y++; /* post = 7, y jadi 8 */
printf("post = y++ : %d, y sekarang = %d\n", post, y); /* 7, 8 */
int pre = ++y; /* y jadi 9, pre = 9 */
printf("pre = ++y : %d, y sekarang = %d\n", pre, y); /* 9, 9 */
/* Ternary */
int max = (a > b) ? a : b;
printf("max(a,b) = %d\n", max); /* 10 */
/* Comma operator: evaluasi kiri ke kanan, hasilkan operand terakhir */
int counter = 0;
int z = (step(&counter), step(&counter), step(&counter));
printf("z (comma) = %d, counter = %d\n", z, counter); /* 3, 3 */
/* sizeof */
printf("sizeof(int) = %zu\n", sizeof(int)); /* 4 */
printf("sizeof(double) = %zu\n", sizeof(double)); /* 8 */
return 0;
}Compile dan jalankan:
gcc -std=c11 -Wall -Wextra -o op1 op1.c
./op1Output yang Dihasilkan:
a + b = 13
a - b = 7
a * b = 30
a / b = 3
a % b = 1
-a = -10
a & b = 2
a | b = 11
a ^ b = 9
~a = -11
a << 2 = 40
a >> 1 = 5
a > b : 1
(a > b) && (c > 0) : 1
(a < b) || (c > 0) : 1
! (a > b) : 0
x += 5 -> 105
x <<= 3 -> 24
x &= 0xF -> 8
post = y++ : 7, y sekarang = 8
pre = ++y : 9, y sekarang = 9
max(a,b) = 10
z (comma) = 3, counter = 3
sizeof(int) = 4
sizeof(double) = 8Mari kita telaah baris-baris kode di atas:
- Baris 4 (
static int step(int *p)): Fungsi pembantu yang menginkrement*plalu mengembalikan nilai baru. Kita pakai ini untuk mendemonstrasikan comma operator dengan efek samping yang terlihat. - Baris 21 (
a / b): Pembagian integer membuang sisa. Hasil10 / 3adalah3, bukan3.33. Untuk pembagian pecahan, keduanya harus cast kedoublelebih dulu. - Baris 33 (
~a): Bitwise NOT membalik semua bit. Untukint32-bit dengan two’s complement,~10 = -11karena~x = -x - 1. - Baris 53 (
int z = (step(&counter), step(&counter), step(&counter));): Comma operator mengevaluasi setiap operand dari kiri ke kanan, lalu menghasilkan nilai operand paling kanan. Di sinicounterdipertambah tiga kali menjadi3, danzmenerima nilai terakhir3. - Baris 56 (
sizeof(int)):sizeofmengembalikan tipesize_t—kita pakai%zusebagai format specifier agar portable di platform 32-bit maupun 64-bit.
Jebakan Umum #
| Jebakan | Contoh Bermasalah | Perbaikan |
|---|---|---|
| Lupa precedence bitwise | a & b == 0 (dievaluasi a & (b == 0)) | (a & b) == 0 |
| Increment di argumen sama | printf("%d %d", i++, i++) (UB: urutan tak terdefinisi) | Pisahkan ke baris terpisah |
| Assignment vs equality | if (a = b) (selalu true kecuali b=0) | if (a == b) |
| Shift negatif | a << -1 (UB) | Validasi jumlah shift >= 0 |
| Signed overflow | INT_MAX + 1 (UB) | Pakai tipe unsigned atau cek dulu |
Cast dan Konversi Implicit #
C melakukan konversi tipe otomatis (implicit conversion) saat operand memiliki tipe berbeda. Aturan umum: tipe yang “lebih sempit” dipromosikan ke tipe yang “lebih lebar” sebelum operasi dilakukan. Promosi integer (integer promotion) mengubah char, short, dan unsigned char ke int atau unsigned int terlebih dahulu.
| Ekspresi | Konversi | Hasil |
|---|---|---|
char c = 'A'; c + 1 | c dipromosikan ke int | 66 |
int i = 5; i + 2.0 | i dikonversi ke double | 7.0 |
5 / 2 | Integer division | 2 |
5 / 2.0 | 5 dikonversi ke double | 2.5 |
(int)3.99 | Truncation ke int | 3 |
(unsigned)-1 | Reinterpretasi bit | 4294967295 |