Komputer menyimpan setiap nilai sebagai deretan bit. Cara bit-bit tersebut dikelompokkan menentukan apakah kita melihat angka desimal, heksadesimal, oktal, atau biner. Pada Chapter ini kita akan melihat bagaimana satu nilai yang sama bisa ditampilkan dalam beberapa basis berbeda, bagaimana operator bitwise bekerja pada representasi biner, serta bagaimana two’s complement merepresentasikan bilangan negatif. Pemahaman representasi ini krusial untuk kode yang memanipulasi bit, memproses data biner, atau berinteraksi dengan perangkat keras.

Empat Basis yang Didukung C #

C secara native mendukung tiga basis penulisan literal integer: desimal (basis 10), heksadesimal (basis 16, diawali 0x), dan oktal (basis 8, diawali 0). Basis biner (basis 2, diawali 0b) diperkenalkan secara resmi di C23, tetapi sudah lama didukung GCC dan Clang sebagai ekstensi. Function printf menyediakan specifier untuk mencetak nilai dalam basis desimal (%d), heksadesimal (%x), dan oktal (%o), tetapi tidak ada specifier bawaan untuk basis biner—kita harus mencetaknya secara manual dengan operasi bit.

c
#include <stdio.h>

int main(void) {
    int dec = 255;
    int hex = 0xFF;
    int oct = 0377;

    /* Cetak dengan berbagai basis */
    printf("desimal    : %d\n", dec);
    printf("heksadesimal: %x  (0x%x)\n", hex, hex);
    printf("oktal       : %o  (0%o)\n", oct, oct);

    /* Binari: tidak ada specifier standar; manual */
    int v = 13;
    printf("13 dalam binari: ");
    for (int i = 7; i >= 0; i--) {
        printf("%d", (v >> i) & 1);
    }
    printf("\n");
    return 0;
}

Output yang Dihasilkan:

text
desimal    : 255
heksadesimal: ff  (0xff)
oktal       : 377  (0377)
13 dalam binari: 00001101

Mari kita telaah baris-baris kode di atas:

  1. Baris 6 (int hex = 0xFF;): literal 0xFF diinterpretasikan sebagai heksadesimal; nilai sama dengan 255 desimal.
  2. Baris 7 (int oct = 0377;): literal 0377 diinterpretasikan sebagai oktal; nilai 3*64 + 7*8 + 7 = 255.
  3. Baris 11 (%x): mencetak unsigned int dalam heksadesimal huruf kecil; %X untuk huruf besar.
  4. Baris 12 (%o): mencetak unsigned int dalam oktal; tidak ada leading zero otomatis, jadi kita tambahkan manual 0%o.
  5. Baris 16-18: loop untuk mencetak representasi biner 8-bit. Ekspresi (v >> i) & 1 menggeser nilai i posisi ke kanan lalu mengambil bit paling kanan dengan mask & 1.

Operator Bitwise #

C menyediakan enam operator bitwise yang bekerja pada level bit:

OperatorOperasiContoh
&AND bitwisea & b
|OR bitwisea | b
^XOR bitwisea ^ b
~NOT bitwise ( unary)~a
<<shift lefta << n
>>shift righta >> n
c
#include <stdio.h>

int main(void) {
    /* Bitwise operators pada representasi biner */
    unsigned int a = 0b1100;  /* 12 */
    unsigned int b = 0b1010;  /* 10 */

    printf("a       = %u (binari 1100)\n", a);
    printf("b       = %u (binari 1010)\n", b);
    printf("a & b   = %u (AND)\n", a & b);
    printf("a | b   = %u (OR)\n", a | b);
    printf("a ^ b   = %u (XOR)\n", a ^ b);
    printf("~a      = %u (NOT)\n", ~a);
    printf("a << 2  = %u (shift left 2)\n", a << 2);
    printf("a >> 1  = %u (shift right 1)\n", a >> 1);
    return 0;
}

Output yang Dihasilkan:

text
a       = 12 (binari 1100)
b       = 10 (binari 1010)
a & b   = 8 (AND)
a | b   = 14 (OR)
a ^ b   = 6 (XOR)
~a      = 4294967283 (NOT)
a << 2  = 48 (shift left 2)
a >> 1  = 6 (shift right 1)

Pada baris 9, a & b melakukan AND per bit: 1100 & 1010 = 1000 (= 8). Pada baris 10, a | b melakukan OR: 1100 | 1010 = 1110 (= 14). Pada baris 11, a ^ b melakukan XOR (bit sama = 0, bit beda = 1): 1100 ^ 1010 = 0110 (= 6). Pada baris 12, ~a membalik semua bit a; karena a bertipe unsigned int 32 bit, hasilnya adalah 2^32 - 1 - 12 = 4.294.967.283. Pada baris 13, a << 2 menggeser bit a ke kiri 2 posisi: 1100 << 2 = 110000 (= 48). Pada baris 14, a >> 1 menggeser ke kanan 1 posisi: 1100 >> 1 = 110 (= 6).

Two’s Complement untuk Bilangan Negatif #

C menggunakan representasi two’s complement untuk tipe signed pada hampir semua platform modern. Cara membentuk two’s complement adalah membalik semua bit lalu menambah 1. Keunggulan representasi ini adalah penjumlahan biner bekerja sama untuk bilangan positif maupun negatif, dan tidak ada dua representasi untuk nol.

c
#include <stdio.h>

int main(void) {
    /* Two's complement: representasi negatif */
    signed char positive = 65;     /* 'A' */
    signed char negative = -65;

    printf("positive = %d, hex byte = %02X\n", positive, (unsigned char)positive);
    printf("negative = %d, hex byte = %02X\n", negative, (unsigned char)negative);

    /* Bandingkan 0 dengan -0 */
    int zero = 0;
    int neg_zero = ~zero + 1;  /* two's complement of 0 */
    printf("~0 + 1 = %d (sama dengan 0)\n", neg_zero);

    /* Mask bit: ambil 4 bit bawah */
    unsigned int value = 0xABCD;
    unsigned int low_nibble = value & 0x0F;
    unsigned int high_nibble = (value >> 4) & 0x0F;
    printf("value     = 0x%04X\n", value);
    printf("low nibble  = 0x%X\n", low_nibble);
    printf("high nibble = 0x%X\n", high_nibble);
    return 0;
}

Output yang Dihasilkan:

text
positive = 65, hex byte = 41
negative = -65, hex byte = BF
~0 + 1 = 0 (sama dengan 0)
value     = 0xABCD
low nibble  = 0xD
high nibble = 0xC

Pada baris 9, 65 direpresentasikan sebagai byte 0x41 (biner 01000001). Pada baris 10, -65 direpresentasikan sebagai 0xBF (biner 10111111). Cara membentuknya: balik bit 01000001 → 10111110, lalu tambah 1 → 10111111 = 0xBF. Pada baris 14, ~zero + 1 menghasilkan 0 lagi—membuktikan bahwa two’s complement dari 0 adalah 0 sendiri. Pada baris 18-20, mask 0x0F mengambil 4 bit bawah dari 0xABCD yaitu 0xD; mask dan shift (value >> 4) & 0x0F mengambil 4 bit kedua dari bawah yaitu 0xC.

Konversi Antar Basis #

Konversi antar basis biasanya dilakukan oleh printf saat mencetak. Untuk konversi dari string ke integer dengan basis tertentu, C menyediakan fungsi strtol, strtoll, strtoul dari header <stdlib.h>. Fungsi-fungsi ini menerima parameter basis (0 untuk auto-detect dari prefix 0x/0, 2-36 untuk basis eksplisit).

Dengan pemahaman empat basis, operator bitwise, dan two’s complement, kita siap masuk ke pembahasan integer overflow—fenomena yang terjadi saat operasi aritmetika menghasilkan nilai di luar batas tipe.