Setiap program yang berjalan menyimpan datanya di RAM. RAM bisa dibayangkan sebagai deretan kotak berukuran satu byte, dan setiap kotak punya nomor urut yang disebut alamat memori. Saat Anda menulis int umur = 25;, compiler memesan empat kotak berurutan dan menaruh angka 25 di sana. Program lalu mengingat alamat kotak pertamanya.

Kebanyakan bahasa pemrograman menyembunyikan alamat itu dari programmer. Bahasa C justru menyerahkannya ke tangan Anda. Pointer adalah variabel yang isinya bukan data biasa, melainkan alamat memori tempat data lain disimpan. Dengan memegang alamat, program bisa mengubah data dari tempat lain, meminjam memori baru saat berjalan, hingga merangkai struktur data yang panjangnya tidak diketahui sejak awal.

Artikel ini membahas pointer dalam pemrograman. Kata yang sama juga dipakai untuk alat presentasi, penanda di layar komputer, dan poin bahasan rapat. Perbedaannya kami rangkum di bagian akhir.

Pointer Adalah Variabel Penyimpan Alamat Memori

Jadi, apa itu pointer? Secara sederhana, pointer adalah variabel yang menyimpan alamat memori milik variabel lain. Variabel biasa berisi nilai seperti 25 atau huruf "A", sedangkan pointer berisi angka alamat seperti 0x16b81ade8. Pengertian pointer dalam standar bahasa C sedikit lebih luas: pointer bisa menunjuk ke data, ke fungsi, atau tidak menunjuk ke mana pun. Kondisi terakhir ini disebut null pointer.

Cara termudah memahaminya adalah lewat bookmark di browser. Bookmark tidak menyimpan isi halaman web, hanya alamatnya. Saat Anda mengekliknya, browser pergi ke alamat itu dan mengambil isi terbarunya. Pointer bekerja dengan logika yang sama: ia menyimpan lokasi, sedangkan isinya selalu diambil dari lokasi tersebut.

Konsep ini punya asal-usul yang tercatat jelas. Menurut IEEE Computer Society, Harold Lawson mengembangkan konsep pointer variable pada 1964–1965 untuk bahasa PL/I. Atas karya itu, Lawson menerima Computer Pioneer Award pada tahun 2000.

Contoh Pointer di Bahasa C: Operator & dan *

Hampir semua urusan pointer di C bertumpu pada dua tanda. Tanda & (operator address-of) mengambil alamat sebuah variabel. Tanda * (operator dereference) melakukan kebalikannya: pergi ke alamat yang disimpan pointer, lalu membaca atau mengubah isinya.

Contoh pointer dalam bahasa C berikut memperlihatkan keduanya dalam satu program pendek:

C
#include <stdio.h>

int main(void) {
    int umur = 25;
    int *p = &umur;  /* alamat umur */

    printf("alamat umur : %p\n", (void *)&umur);
    printf("isi p       : %p\n", (void *)p);
    printf("nilai *p    : %d\n", *p);

    *p = 30;         /* ubah lewat pointer */
    printf("umur kini   : %d\n", umur);
    return 0;
}

Hasilnya saat kami jalankan di macOS (prosesor arm64, compiler clang):

TEXT
alamat umur : 0x16b81ade8
isi p       : 0x16b81ade8
nilai *p    : 25
umur kini   : 30

Dua baris pertama membuktikan p berisi alamat yang sama persis dengan umur. Baris terakhir menunjukkan hal yang lebih penting: umur berubah menjadi 30 tanpa pernah disebut namanya, karena perubahannya dilakukan lewat pointer. Angka alamat di komputer Anda akan berbeda, bahkan berganti setiap kali program dijalankan. Sistem operasi sengaja mengacak tata letak memori demi keamanan, teknik yang disebut ASLR (Address Space Layout Randomization).

Contoh pointer bahasa C: &umur memberi alamat 0x16b81ade8 ke p, lalu *p = 30 mengubah umur dari 25 menjadi 30.
Contoh pointer bahasa C: &umur memberi alamat 0x16b81ade8 ke p, lalu *p = 30 mengubah umur dari 25 menjadi 30.

Satu jebakan sering membingungkan pemula. Tanda * punya dua arti tergantung letaknya. Di deklarasi int *p, bintang berarti "p adalah pointer ke int". Di ekspresi *p = 30, bintang berarti "isi dari alamat yang disimpan p". Bacalah int * sebagai satu kesatuan tipe, bukan sebagai operasi.

Pointer juga bisa menunjuk ke pointer lain. Deklarasi int **pp = &p; membuat pp menyimpan alamat p, sehingga **pp menempuh dua lompatan sebelum sampai ke nilai umur. Pola pointer ke pointer ini dipakai, misalnya, saat sebuah fungsi perlu mengganti alamat yang disimpan pointer milik pemanggilnya.

Berapa Byte Ukuran Sebuah Pointer?

Karena isinya alamat, ukuran pointer ditentukan oleh lebar alamat di mesin tersebut, bukan oleh tipe data yang ditunjuk. Di sistem 32-bit, pointer berukuran 4 byte. Di sistem 64-bit, baik Windows maupun Linux dan macOS, ukurannya 8 byte. Baris berikut memeriksa empat jenis pointer sekaligus:

C
printf("%zu %zu %zu %zu\n",
       sizeof(int *), sizeof(char *),
       sizeof(double *), sizeof(void *));

Hasilnya di mesin 64-bit kami adalah 8 8 8 8. Pointer ke char yang menunjuk data 1 byte ternyata sama besarnya dengan pointer ke double yang menunjuk data 8 byte.

Lalu, kenapa tipe tetap harus ditulis saat mendeklarasikan pointer? Tipe memberi tahu compiler dua hal. Pertama, berapa byte yang dibaca saat pointer didereferensi: *p pada int * membaca 4 byte, sedangkan pada char * hanya 1 byte. Kedua, seberapa jauh pointer bergeser saat ditambah satu. Ukuran setiap tipe data karena itu ikut menentukan perilaku pointernya.

Standar C tidak mewajibkan semua jenis pointer berukuran sama. Keseragaman 8 byte di atas adalah sifat platform 64-bit yang umum (model data LP64 dan LLP64), bukan janji bahasa.

Aritmetika Pointer: Kenapa p + 1 Melompat 4 Byte

Pointer bisa dijumlahkan dengan bilangan bulat. Menambah satu pada pointer tidak menggeser alamat sebesar satu byte, melainkan sebesar ukuran satu elemen yang ditunjuk. Perilaku inilah yang disebut aritmetika pointer.

C
int arr[4] = {10, 20, 30, 40};
int *p = arr;   /* sama dengan &arr[0] */

for (int i = 0; i < 4; i++)
    printf("p+%d -> %p, nilai %d\n",
           i, (void *)(p + i), *(p + i));

Output di komputer kami:

TEXT
p+0 -> 0x16d596dd0, nilai 10
p+1 -> 0x16d596dd4, nilai 20
p+2 -> 0x16d596dd8, nilai 30
p+3 -> 0x16d596ddc, nilai 40

Perhatikan dua digit terakhir alamatnya: d0, d4, d8, dc. Setiap langkah maju tepat 4 byte, sesuai ukuran int. Seandainya p bertipe double *, lompatannya menjadi 8 byte. Hubungan ini pula yang membuat arr[i] dan *(arr + i) bermakna sama, seperti dijelaskan dalam pembahasan cara kerja indeks array.

Aritmetika pointer: p sampai p+3 menunjuk int 10, 20, 30, 40 yang alamatnya naik 4 byte; sizeof(arr) 16, sizeof(p) 8.
Aritmetika pointer: p sampai p+3 menunjuk int 10, 20, 30, 40 yang alamatnya naik 4 byte; sizeof(arr) 16, sizeof(p) 8.

Baris int *p = arr; menyimpan satu pelajaran lagi. Nama array otomatis "meluruh" (array decay) menjadi pointer ke elemen pertamanya. Meski begitu, array bukan pointer. Di program yang sama, sizeof(arr) bernilai 16 karena menghitung empat int, sedangkan sizeof(p) hanya 8 karena menghitung satu alamat.

Fungsi Pointer dalam Program Nyata

Berikut lima fungsi pointer yang paling sering Anda temui dalam program nyata:

  1. Mengubah variabel milik pemanggil: Bahasa C selalu menyalin argumen saat memanggil fungsi (pass by value). Dengan mengirim alamat, kita meniru pass by reference sehingga fungsi bisa mengubah variabel aslinya.
  2. Meminjam memori saat program berjalan: Fungsi malloc meminjamkan blok memori dari heap (area memori dinamis) dan mengembalikan alamatnya sebagai pointer. Blok itu wajib dikembalikan dengan free setelah selesai dipakai.
  3. Merangkai struktur data: Linked list, tree, dan graph menyambungkan elemennya lewat pointer. Setiap simpul menyimpan alamat simpul berikutnya, sehingga struktur data bisa tumbuh tanpa harus bersebelahan di memori.
  4. Mengoper data besar tanpa menyalin: Mengirim alamat sebuah struct berukuran 1 MB ke fungsi hanya memindahkan 8 byte, bukan 1 MB.
  5. Menyimpan fungsi sebagai data: Pointer ke fungsi seperti int (*f)(int) memungkinkan sebuah fungsi diteruskan ke fungsi lain sebagai callback. Fungsi pengurut qsort di pustaka standar C bekerja dengan cara ini.

Poin pertama paling mudah dilihat pada fungsi penukar nilai. Dua fungsi berikut tampak mirip, tetapi hanya yang kedua benar-benar bekerja:

C
void tukar_salah(int a, int b) {
    int t = a; a = b; b = t;
}

void tukar(int *a, int *b) {
    int t = *a; *a = *b; *b = t;
}

Dengan x = 1 dan y = 2, pemanggilan tukar_salah(x, y) menghasilkan x=1 y=2, karena yang ditukar hanya salinannya. Pemanggilan tukar(&x, &y) menghasilkan x=2 y=1, karena fungsi kedua bekerja langsung pada alamat milik pemanggil.

Fungsi pointer: tukar_salah(x, y) hanya menukar salinan sehingga x=1 y=2, sedangkan tukar(&x, &y) menghasilkan x=2 y=1.
Fungsi pointer: tukar_salah(x, y) hanya menukar salinan sehingga x=1 y=2, sedangkan tukar(&x, &y) menghasilkan x=2 y=1.

Kelemahan Pointer: Empat Bug yang Paling Sering Muncul

Kebebasan memegang alamat memori datang bersama risiko besar. Compiler C memercayai alamat yang Anda berikan, benar maupun salah. Empat kesalahan berikut menjadi sumber masalah paling umum:

  1. Null pointer: Pointer bernilai NULL tidak menunjuk ke mana pun. Mendereferensikannya umumnya membuat program berhenti mendadak dengan pesan segmentation fault, dan di dalam kernel Linux kesalahan yang sama bisa berujung kernel panic. Tony Hoare, yang memperkenalkan null reference di bahasa ALGOL W pada 1965, menyebutnya "kesalahan miliaran dolar" dalam presentasinya di QCon 2009.
  2. Dangling pointer: Pointer yang masih menyimpan alamat memori yang sudah tidak berlaku, misalnya sesudah free atau alamat variabel lokal milik fungsi yang sudah selesai. Kondisinya seperti bookmark ke halaman yang sudah dihapus: alamatnya masih ada, isinya tidak lagi bisa dipercaya.
  3. Wild pointer: Pointer yang dideklarasikan tanpa diberi nilai awal. Isinya alamat acak sisa memori, sehingga menulis lewat pointer ini bisa merusak data mana saja.
  4. Memory leak: Memori hasil malloc yang tidak pernah di-free. Program yang berjalan lama, seperti server, makin lama makin memakan RAM sampai kehabisan.
Empat bug pointer: null pointer tak menunjuk apa pun, dangling pointer ke memori yang dilepas, wild pointer, dan memory leak.
Empat bug pointer: null pointer tak menunjuk apa pun, dangling pointer ke memori yang dilepas, wild pointer, dan memory leak.

Tim keamanan Chromium mencatat sekitar 70% bug keamanan tingkat tinggi di browser tersebut berasal dari kesalahan memori, yang mereka gambarkan sebagai kesalahan pointer C/C++. Microsoft melaporkan angka serupa untuk kerentanan yang mereka tambal pada 2006–2018. Atas dasar itu, CISA dan NSA pada Juni 2025 kembali mendorong pengembang memakai bahasa memory-safe untuk perangkat lunak baru.

Cara Aman Bekerja dengan Pointer

Bagi pemula yang sedang belajar C, lima kebiasaan berikut sudah mencegah sebagian besar bug di atas:

  1. Selalu beri nilai awal: Tulis int *p = NULL; jika alamatnya belum tersedia. Pointer bernilai NULL mudah diperiksa, sedangkan pointer acak tidak.
  2. Periksa sebelum memakai: malloc mengembalikan NULL saat memori tidak tersedia. Periksa dengan if (p == NULL) sebelum mendereferensikannya.
  3. Satu malloc, satu free: Pasangkan setiap alokasi dengan tepat satu free. Memanggil free dua kali pada alamat yang sama sama berbahayanya dengan lupa memanggilnya.
  4. Kosongkan setelah free: Langsung isi pointer dengan NULL setelah free, supaya tidak tersisa dangling pointer.
  5. Biarkan compiler membantu: Kompilasi selalu dengan -Wall -Wextra. Saat latihan, tambahkan AddressSanitizer lewat opsi -fsanitize=address.

Saat kami mengompilasi contoh wild pointer dan dangling pointer dengan cc -Wall, clang langsung memberi dua peringatan berikut:

TEXT
warning: address of stack memory associated
  with local variable 'x' returned
  [-Wreturn-stack-address]
warning: variable 'liar' is uninitialized
  when used here [-Wuninitialized]

Peringatan pertama menandai fungsi yang mengembalikan alamat variabel lokalnya, sedangkan yang kedua menandai pointer liar yang dipakai sebelum diberi nilai. Bug membaca memori sesudah free memang lolos kompilasi. Namun, AddressSanitizer menghentikan program tersebut saat dijalankan dengan laporan heap-use-after-free.

Urutan belajar yang kami sarankan ada empat tahap. Kuasai & dan * dulu, lanjut ke hubungan pointer dengan array, lalu pointer sebagai parameter fungsi. Baru setelah itu masuk ke malloc, free, dan struktur data berantai.

Pointer di C++, Go, Rust, Java, dan Python

Bahasa yang lebih baru tidak menghapus pointer. Mereka membatasi apa yang boleh dilakukan programmer terhadapnya:

  • C++: Mewarisi seluruh pointer C, lalu menambahkan nullptr sejak C++11 sebagai pengganti NULL yang lebih aman. C++ juga menyediakan smart pointer seperti std::unique_ptr yang membebaskan memori secara otomatis. Standar C23 kini ikut mengadopsi nullptr.
  • Go: Punya pointer dengan operator & dan * yang sama, tetapi dokumentasi resminya menegaskan Go tidak mengenal aritmetika pointer. Mendereferensikan pointer nil di Golang memicu panic, bukan kerusakan memori diam-diam.
  • Rust: Memakai reference yang keabsahannya diperiksa compiler. Raw pointer tetap tersedia, tetapi mendereferensikannya hanya boleh dilakukan di dalam blok unsafe.
  • Java: Spesifikasi bahasanya menyebut referensi sebagai pointer ke objek, hanya saja tanpa operator alamat dan tanpa aritmetika. Mengakses objek lewat referensi kosong di Java memunculkan galat NullPointerException.
  • Python: Setiap variabel adalah nama yang merujuk ke objek. Fungsi id() di CPython mengembalikan alamat objek di memori, meski Python tidak pernah mengizinkan Anda memanipulasinya langsung.

Jadi, memahami pointer tetap berguna walaupun Anda tidak menulis C. Konsep yang sama muncul dalam bentuk referensi di hampir setiap bahasa modern.

Kata "Pointer" di Luar Pemrograman

Di luar dunia kode, pointer artinya penunjuk, dan maknanya bergantung pada konteks:

  • Pointer presentasi: Alat genggam untuk menggeser slide, umumnya dilengkapi sinar laser sehingga disebut juga laser pointer.
  • Pointer mouse: Penanda di layar yang bergerak mengikuti mouse atau touchpad.
  • Cell pointer: Kotak bergaris tebal di Microsoft Excel yang menandai sel aktif.
  • Pointer rapat: Poin-poin bahasan singkat yang disiapkan sebelum rapat atau sambutan.

Benang merahnya sama dengan pointer dalam pemrograman: sesuatu yang menunjuk ke hal lain tanpa menjadi hal itu sendiri.

Pertanyaan yang Sering Diajukan

Apa fungsi pointer dalam C++?

Fungsinya sama dengan di C: mengakses dan mengubah data lewat alamat, mengelola memori dinamis, dan membangun struktur data. Bedanya, C++ menganjurkan smart pointer dan reference (int &r) untuk sebagian besar kebutuhan, sehingga pointer mentah lebih jarang ditulis langsung.

Apa beda pointer dan variabel biasa?

Variabel biasa menyimpan nilai, misalnya 25. Pointer menyimpan alamat tempat sebuah nilai berada. Untuk mendapatkan nilai lewat pointer, Anda perlu operator *.

Apa itu pointer ke pointer?

Pointer ke pointer (pointer to pointer) adalah pointer yang menyimpan alamat pointer lain, dideklarasikan dengan dua bintang seperti int **pp. Bentuk ini umum dijumpai pada array dua dimensi dinamis dan parameter char **argv di fungsi main.

Apakah pointer sama dengan kursor?

Dalam percakapan sehari-hari keduanya dianggap sama, yaitu penanda di layar yang digerakkan mouse atau touchpad. Sebagian dokumentasi membedakan pointer mouse dari kursor teks, garis tegak berkedip yang menandai posisi ketikan. Pointer dalam pemrograman adalah hal lain sama sekali, karena ia tidak terlihat di layar.

Elemen struktur data yang berisi pointer disebut apa?

Elemen tersebut disebut simpul atau node. Pada linked list, setiap node berisi dua bagian: data dan pointer ke node berikutnya, yang lazim diberi nama next atau link.

Apa arti null pointer exception?

NullPointerException adalah galat di Java yang muncul ketika program memakai referensi bernilai null, misalnya memanggil method dari objek yang belum dibuat. Pesan ini kadang terlihat oleh pengguna biasa di aplikasi berbasis Java. Penyebabnya hampir selalu ada di kode aplikasi, sehingga perbaikannya menjadi tugas pengembang.

Kesimpulan

Pointer adalah variabel yang menyimpan alamat memori, dan tipenya menentukan berapa byte yang dibaca serta seberapa jauh ia melompat. Lewat operator & dan *, pointer memungkinkan fungsi mengubah data pemanggil, meminjam memori saat program berjalan, dan merangkai struktur data. Harga kebebasan itu adalah kelas bug yang menyumbang sekitar 70% masalah keamanan serius di perangkat lunak besar.

Jika Anda belajar C, C++, atau pemrograman embedded, pointer wajib dikuasai sampai lancar. Jika Anda bekerja dengan Go, Java, atau Python, cukup pahami konsep referensinya, karena galat seperti NullPointerException berakar dari gagasan yang sama. Semoga artikel ini membantu.