Latihan Pointer
Latihan membuat instruksi pembelajaran tentang Pointer, Referensi, serta implementasi yang aman di pemrograman Rust menggunakan ownership, borrowing dan reference.
Tujuan Pembelajaran
Memahami konsep pointer secara aman menggunakan mekanisme Rust: ownership, borrowing, dan reference.
Mengenali perbedaan referensi immutable (
&T
) dan mutable (&mut T
).Memahami alasan Rust mencegah dangling pointer dengan compile-time checking.
Menerapkan
Box
untuk mengembalikan data dari fungsi dengan aman.Memahami hubungan array/slice dan pointer serta akses memori aman vs
unsafe
.
Prasyarat
Dasar bahasa pemrograman Rust (variabel,
mut
, fungsi sederhana).Pemahaman awal stack vs heap.
Mengetahui cara menjalankan kode di play.rust-lang.org.
Latihan 1: Referensi dan Dereferensi
Contoh Sederhana (Pendahuluan)
Sebelum masuk ke pointer-to-pointer, mari lihat contoh paling dasar:
fn main() {
let mut x = 10;
let r = &x; // immutable borrow
println!("r = {}", r);
let rp = &mut x; // mutable borrow
*rp = 20; // dereference untuk mengubah nilai
println!("x = {}", x);
}
Penjelasan Singkat
&x
meminjam nilaix
untuk dibaca.&mut x
meminjam untuk diubah.*rp = 20
berarti "akses nilai yang dirujuk" lalu ubah isinya.
Latihan 1 (Pointer-to-Pointer Sederhana)
Buat program yang mengeksekusi langkah berikut:
Deklarasi dua variabel
s
dant
(keduanyamut
).Buat referensi mutable ke
s
(ps
), lalu buat referensi mutable keps
(pps
).Ubah nilai
s
melaluipps
, lalu buatpt
meminjams
melaluips
.Ubah nilai
s
melaluipt
, lalu copy nilais
ket
.Cetak nilai akhir
s
dant
.
fn main() {
let mut s = 1;
let mut t = 1;
let mut ps: &mut i32 = &mut s;
let mut pps: &mut &mut i32 = &mut ps;
let mut pt: &mut i32 = &mut t;
**pps = 2; // ubah nilai s lewat pps
pt = ps; // pt sekarang menunjuk s
*pt = 3; // ubah s jadi 3
t = s; // copy nilai s ke t
println!("s = {}, t = {}", s, t);
}
Clue
Ikuti perubahan s
dari awal. Pertama s = 2
, lalu s = 3
, lalu t
disamakan dengan s
. Hasil akhirnya s = 3, t = 3
.
Latihan 2: Mengembalikan Data dari Fungsi
Soal
Buat fungsi yang mencoba mengembalikan referensi ke variabel lokal.
Perhatikan pesan error.
Perbaiki fungsi agar mengembalikan
Box<i32>
.
Contoh Jawaban
fn good_return_box() -> Box<i32> {
Box::new(42) // alokasi heap
}
fn main() {
let val = good_return_box();
println!("val = {}", *val); // dereference Box
}
Clue
Referensi ke variabel lokal tidak bisa keluar scope (akan error).
Box::new
memindahkan data ke heap, sehingga bisa dikembalikan dengan aman.
Latihan 3: Array dan Pointer-like Access
Soal
Diberikan array ['I','T','B']
, akses dan tampilkan tiap elemen:
Gunakan indeks
[i]
.Gunakan
get(i)
yang mengembalikanOption<&T>
.Iterasi dengan
for
.
Tambahan opsional: tampilkan elemen kedua menggunakan raw pointer
dalam blok unsafe
.
Contoh Jawaban
fn main() {
let blocks = ['I', 'T', 'B'];
println!("blocks[0] = {}", blocks[0]);
if let Some(ch) = blocks.get(1) {
println!("blocks.get(1) = {}", ch);
}
for (i, &c) in blocks.iter().enumerate() {
println!("blocks[{}] = {}", i, c);
}
unsafe {
let ptr = blocks.as_ptr();
println!("raw pointer second = {}", *ptr.add(1));
}
}
Clue
blocks[10]
akan panic.blocks.get(10)
mengembalikanNone
, aman dari panic.unsafe
harus dipakai hati-hati: tidak ada proteksi boundary.
Edge Cases
Latihan 1: jika kita mencoba membuat dua
&mut
aktif sekaligus, akan gagal compile.Latihan 2: jika kita mengembalikan referensi ke data lokal, compiler menolak karena akan jadi dangling pointer.
Latihan 3: akses di luar batas array akan menyebabkan panic.
Pertanyaan Refleksi & Clue
Mengapa Rust mencegah dangling pointer? → Untuk mencegah akses ke memori yang sudah di-drop, sehingga program tidak crash di runtime.
Apa yang akan terjadi jika kita menukar urutan
pt = ps
dan**pps = 2
? → Nilai yang dipinjam akan berbeda, hasil akhirnya juga bisa berbeda, ini latihan melacak alur program.Kapan
Box<T>
lebih tepat digunakan dibanding mengembalikan nilai biasa? → Saat kita butuh alokasi heap (misalnya data besar, atau ukuran tidak diketahui di compile-time).Apa risiko pointer arithmetic di
unsafe
? → Jika salah perhitungan offset, bisa membaca memori yang salah → undefined behavior.
Alat Bantu Visualisasi
Rustviz dapat digunakan untuk melihat hubungan ownership dan borrow secara grafis.
Rust Playground untuk menjalankan contoh kode cepat dan melihat error message.
VSCode + Rust Analyzer memberi inline hint saat menulis kode, membantu memahami lifetimes.
Referensi
Materi ini diadaptasi dari:
Sekolah Teknik Elektro dan Informatika, Institut Teknologi Bandung. Materi Pointer dan Memori (dengan penyesuaian untuk Rust).
Dokumentasi resmi Rust: The Rust Programming Language, bab Ownership, Borrowing, dan Smart Pointers.
Nick Parlante, Memory and Pointers – Stanford CS Education Library.