Sebelum bicara pointer, kita perlu sepakat dulu tentang bagaimana komputer menyimpan data. Memori (RAM) bisa kita bayangkan sebagai barisan panjang kotak-kotak kecil, dan setiap kotak berukuran satu byte dengan nomor urutnya sendiri. Nomor urut itulah yang disebut alamat memori (memory address): identitas unik yang menunjukkan posisi sebuah byte di dalam RAM. Setiap kali kita mendeklarasikan variabel, compiler menempatkannya pada satu atau beberapa byte tertentu, dan alamat byte pertamanya dapat kita minta kapan saja. Pada Chapter ini kita mengenal konsep tersebut, memakai operator address-of &, dan melihat seperti apa tampilan alamat di terminal.

Memori sebagai Barisan Byte #

Satu byte adalah unit terkecil yang dapat dialamatkan, terdiri atas 8 bit. Tipe fundamental menempati jumlah byte yang berbeda: char umumnya 1 byte, int 4 byte, dan double 8 byte pada platform yang kita pakai. Angka-angka ini bukan tebakan, tetapi bisa kita periksa dengan sizeof seperti yang sudah kita latih pada Chapter sizeof dan limits. Variabel int yang menempati 4 byte berarti “meminjam” empat kotak berurutan di memori, misalnya byte ke-1000, ke-1001, ke-1002, dan ke-1003.

Compiler-lah yang memutuskan variabel apa diletakkan di mana; kita sebagai programmer tidak pernah memilih nomor kotaknya secara langsung. Yang bisa kita lakukan adalah bertanya: “di alamat berapa variabel ini berada?” Pertanyaan itu dijawab oleh operator address-of.

Operator Address-of (&) #

Operator & yang diletakkan di depan nama variabel menghasilkan alamat variabel tersebut. Ekspresi &stok dibaca “alamat dari stok”. Perhatikan bahwa & di sini berbeda peran dengan & bitwise yang kita pelajari pada Chapter Operator Bitwise — konteks penggunaannya membedakan keduanya.

cpp
#include <cstddef>
#include <iostream>

int main() {
    int stok = 25;
    int harga = 4000;
    int gudang[4] = {10, 20, 30, 40};

    // Alamat setiap objek unik — kita bandingkan alamatnya, bukan mencetaknya
    std::cout << "Alamat stok berbeda dari harga : " << (&stok != &harga) << "\n";

    // Memori adalah barisan byte; sizeof menunjukkan berapa byte yang dihuni
    std::cout << "sizeof(char)  : " << sizeof(char) << " byte\n";
    std::cout << "sizeof(int)   : " << sizeof(int) << " byte\n";
    std::cout << "sizeof(double): " << sizeof(double) << " byte\n";

    // Selisih alamat dua elemen bertetangga (deterministik, bukan alamat mentah)
    std::ptrdiff_t jarak =
        reinterpret_cast<const char*>(&gudang[1]) -
        reinterpret_cast<const char*>(&gudang[0]);
    std::cout << "Jarak &gudang[0] ke &gudang[1] : " << jarak << " byte\n";

    return 0;
}

Output yang Dihasilkan:

text
Alamat stok berbeda dari harga : 1
sizeof(char)  : 1 byte
sizeof(int)   : 4 byte
sizeof(double): 8 byte
Jarak &gudang[0] ke &gudang[1] : 4 byte

Mari kita bedah program di atas:

  1. Baris 13 (&stok != &harga): kita membandingkan dua alamat, bukan mencetaknya. Hasilnya 1 (berarti true) karena dua variabel berbeda selalu berada di alamat yang berbeda.
  2. Baris 16-18 (sizeof ...): mengonfirmasi bahwa char menempati 1 byte, int 4 byte, dan double 8 byte di platform 64-bit yang kita gunakan.
  3. Baris 21-23 (jarak): &gudang[1] dan &gudang[0] adalah alamat mentah; agar selisihnya bisa dicetak dalam satuan byte, keduanya di-cast ke const char* (pointer ke byte) terlebih dahulu. Hasilnya selalu 4 — dua elemen int bertetangga berjarak persis sizeof(int) byte.
  4. Baris 21 (std::ptrdiff_t): tipe baku untuk menyimpan hasil pengurangan dua alamat, dideklarasikan di header <cstddef>.

Seperti Apa Tampilan Alamat Itu #

Sesekali kita memang perlu mencetak alamat untuk keperluan debugging. Contoh berikut menampilkan bentuk khasnya:

cpp Contoh tampilan (alamat bervariasi)
#include <iostream>

int main() {
    int stok = 25;
    std::cout << &stok << "\n";   // mencetak alamat stok
    return 0;
}
text Salah satu hasil eksekusi
0x7ffccbe63d2c

Alamat dicetak dalam notasi heksadesimal (bilangan basis 16) yang diawali 0x — format standar untuk menampilkan alamat memori. Ada satu hal penting yang harus kita tanam sejak sekarang: nilai alamat tidak deterministik. Pada mesin yang sama, program di atas bisa mencetak 0x7ffccbe63d2c pada satu eksekusi dan 0x7ffe4638130c pada eksekusi berikutnya, karena sistem operasi modern menerapkan ASLR (Address Space Layout Randomization) — teknik mengacak posisi memori program setiap kali dijalankan sebagai benteng tambahan terhadap eksploitasi. Karena itu, dalam pembelajaran dan pengujian, kita tidak pernah mengandalkan angka alamat mentah; yang stabil dan dapat diverifikasi adalah hubungan antaralamat (sama atau berbeda, dekat atau jauh) serta nilai yang tersimpan di alamat tersebut.

Dari sini lompatannya wajar: bila alamat bisa dijadikan nilai yang disimpan, kita butuh tipe variabel penampungnya. Tipe itulah pointer — pokok bahasan Chapter berikutnya.

Referensi: cppreference — pointer declaration , cppreference — sizeof .