Pointer tanpa dereference hanya sekadar kertas berisi nomor rumah yang tidak pernah kita masuki. Dereference (menguraikan referensi) adalah operasi yang benar-benar “mengunjungi” alamat yang ditunjuk pointer: membaca nilai yang tersimpan di sana, atau bahkan menimpanya dengan nilai baru. Operatornya adalah * — tanda yang sama dengan deklarasi pointer, tetapi maknanya berbeda sesuai konteks. Pada Chapter ini kita melatih dereference untuk membaca dan menulis, membedah aturan precedence yang sering mengejutkan pemula, dan memahami satu aturan emas: dereference hanya boleh dilakukan pada pointer yang sah.
Membaca dan Menulis Melalui Pointer #
Satu operator *, dua arah kerja. Ketika dipakai di sisi kanan, *p membaca nilai di alamat yang ditunjuk p; ketika dipakai di sisi kiri assignment, *p = ... menulis ke alamat tersebut. Keduanya bekerja pada objek aslinya, bukan salinannya.
#include <iostream>
int main() {
int x = 10;
int* p = &x;
// Membaca melalui pointer
std::cout << "*p saat ini : " << *p << "\n";
// Menulis melalui pointer: mengubah x tanpa menyentuh variabelnya langsung
*p = 42;
std::cout << "x setelah *p = 42 : " << x << "\n";
*p = *p + 8;
std::cout << "x setelah *p + 8 : " << x << "\n";
++*p; // parse: ++(*p) — menaikkan nilai yang ditunjuk, bukan pointernya
std::cout << "x setelah ++*p : " << x << "\n";
// Precedence: *a + 1 berbeda dengan *(a + 1)
int arr[3] = {5, 15, 25};
int* a = arr; // menunjuk arr[0]
std::cout << "*a + 1 = " << *a + 1 << " (nilai arr[0] ditambah 1)\n";
std::cout << "*(a+1) = " << *(a + 1) << " (nilai arr[1])\n";
return 0;
}Output yang Dihasilkan:
*p saat ini : 10
x setelah *p = 42 : 42
x setelah *p + 8 : 50
x setelah ++*p : 51
*a + 1 = 6 (nilai arr[0] ditambah 1)
*(a+1) = 15 (nilai arr[1])Bedah baris-per-baris:
- Baris 9 (
*pdi sisi kanan): compiler melihatpberisi alamatx, pergi ke alamat itu, membaca 4 byte dengan tata letakint, dan hasilnya 10. - Baris 13 (
*p = 42;):*di sisi kiri membuat compiler menulis 42 ke alamat yang ditunjukp. Karenapmenunjukx, nilaixikut berubah — kita tidak pernah menulisxsecara langsung, tetapixberubah. - Baris 15-17 (
*p = *p + 8;): sisi kanan membaca nilai saat ini (42), menambahkannya 8, lalu hasilnya ditulis kembali ke alamat yang sama. Pola baca-ubah-tulis seperti ini sangat umum. - Baris 18 (
++*p;): karena operator unary dijalankan kanan-ke-kiri, ekspresi ini di-parse sebagai++(*p)— menaikkan nilai yang ditunjuk, sehinggaxmenjadi 51. Pointerpsendiri tidak bergeser. - Baris 21-27 (precedence):
*a + 1berarti(*a) + 1karena*lebih kuat mengikat daripada+, hasilnya 5 + 1 = 6. Sebaliknya*(a+1)menghitung alamata+1dulu (satu elemenintke kanan, menjelajah kearr[1]), baru dereference: 15. Kurung menentukan segalanya.
Dereference pada Pointer yang Belum Siap #
Aturan emasnya sederhana: *p hanya boleh dieksekusi bila p berisi alamat objek yang masih hidup. Pointer yang baru dideklarasikan tanpa inisialisasi berisi nilai acak (alamat sampah), dan melakukan dereference padanya adalah undefined behavior — situasi di mana standar C++ tidak menjamin apa pun:
int main() {
int* p; // berisi alamat sampah, bukan nullptr
int v = *p; // UNDEFINED BEHAVIOR: membaca alamat acak
std::cout << v;
}Program seperti ini bisa saja crash, bisa mencetak angka tidak masuk akal, bahkan tampak “berjalan normal” lalu merusak data di tempat lain — semuanya tanpa pesan error yang jelas dari compiler. Tidak ada cara yang bisa diandalkan untuk memeriksa apakah pointer tanpa inisialisasi berisi alamat sah; oleh karena itu pencegahannya ada di tangan kita: selalu inisialisasi pointer saat deklarasi, dengan alamat &variabel atau dengan nullptr bila memang belum ada sasarannya. nullptr sendiri adalah topik Chapter berikutnya, dan pointer yang menunjuk objek yang sudah tidak hidup (dangling pointer) dibahas pada bagian akhir Section ini.
Sekarang kita sudah bisa membaca dan menulis melalui pointer. Namun ada satu nilai spesial yang wajib dikuasai sebelum melangkah lebih jauh: cara menyatakan “pointer ini sedang tidak menunjuk apa-apa” dengan aman dan eksplisit.
Referensi: cppreference — operator precedence , cppreference — undefined behavior .