Episode ini membedah pointer, jantung dari bahasa C: alamat memori, dereference, pointer terhadap array, string, dan fungsi, dynamic memory allocation dengan malloc, calloc, realloc, dan free, serta pointer safety dan bug umum seperti use-after-free dan null pointer.

Pointer adalah fitur yang membuat C istimewa sekaligus paling berbahaya. Sebuah pointer menyimpan alamat memori sebuah nilai, bukan nilai itu sendiri. Dengan pointer, kalian bisa memanipulasi data besar tanpa menyalin, membangun struktur data dinamis, dan memanggil fungsi secara tidak langsung.
Episode 7 membahas dasar pointer dan dereference, pointer terhadap array, string, dan fungsi, alokasi memori dinamis dengan malloc, calloc, realloc, dan free, serta pola keselamatan yang mencegah bug klasik seperti null pointer dereference dan use-after-free.
Penguasaan pointer adalah garis pembatas antara programmer yang menulis kode C dan programmer yang benar-benar memahami C. Episode ini adalah investasi paling penting di seluruh series.
Setiap variabel memiliki alamat di memori. Operator & mengambil alamat sebuah variabel, dan tipe pointer dideklarasikan dengan tanda bintang setelah tipe dasar:
cat > pointer.c <<'EOF'
#include <stdio.h>
int main(void) {
int nilai = 42;
int *alamat = &nilai;
printf("Nilai: %d\n", nilai);
printf("Alamat: %p\n", (void *)alamat);
printf("Dereference: %d\n", *alamat);
return 0;
}
EOF
gcc -Wall -Wextra pointer.c -o pointer && ./pointerint *alamat = &nilai menyimpan alamat nilai ke dalam pointer alamat. Operator * saat dipakai di depan pointer disebut dereference, yaitu membaca nilai yang ditunjuk. %p mencetak alamat dalam bentuk heksadesimal.
Pointer memungkinkan fungsi memodifikasi argumen asli, mengatasi keterbatasan passing by value dari episode 5:
void tambah_satu(int *x) {
(*x)++;
}
int main(void) {
int angka = 10;
tambah_satu(&angka);
printf("%d\n", angka);
return 0;
}Fungsi tambah_satu(&angka) menerima alamat angka dan mengubah nilai aslinya lewat dereference. Tanpa pointer, perubahan hanya berlaku pada salinan di dalam fungsi.
Nama sebuah array bertindak sebagai pointer ke elemen pertamanya. Ini berarti nilai dan &nilai[0] menunjuk alamat yang sama. Aritmatika pointer memungkinkan iterasi elemen:
int nilai[5] = {10, 20, 30, 40, 50};
for (int *p = nilai; p < nilai + 5; p++) {
printf("%d ", *p);
}Iterasi for (int *p = nilai; ...; p++) memajukan pointer satu elemen per langkah, bukan satu byte. Ukuran langkah ditentukan oleh tipe pointer, sehingga int maju 4 byte pada platform umum.
String yang tak dapat diubah disimpan sebagai pointer ke char: const char *s = "teks". Pointer ke fungsi, seperti yang diperkenalkan di episode 5, menyimpan alamat fungsi sehingga fungsi bisa dipilih saat runtime. Keduanya menunjukkan bahwa pointer adalah konsep umum, bukan khusus data saja.
Memori heap dialokasikan saat runtime melalui empat fungsi dari <stdlib.h>:
malloc: mengalokasikan byte tanpa menginisialisasi.calloc: mengalokasikan dan mengisi nol.realloc: mengubah ukuran blok yang sudah ada.free: melepaskan blok kembali ke sistem.cat > alokasi.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *data = malloc(5 * sizeof(int));
if (data == NULL) {
return 1;
}
for (int i = 0; i < 5; i++) {
data[i] = i * i;
}
int *besar = realloc(data, 10 * sizeof(int));
if (besar != NULL) {
data = besar;
}
free(data);
return 0;
}
EOF
gcc -Wall -Wextra alokasi.c -o alokasi && ./alokasiPola malloc(5 * sizeof(int)) mengalokasikan cukup memori untuk 5 int. Selalu periksa hasil NULL karena alokasi bisa gagal. realloc mengembalikan pointer baru yang mungkin berbeda, dan free harus dipanggil tepat sekali untuk setiap blok.
Kebocoran memori terjadi ketika blok dialokasikan tetapi tidak pernah di-free. Deteksi dengan valgrind:
valgrind --leak-check=full ./alokasiOutput valgrind --leak-check=full ./alokasi melaporkan blok yang belum di-free. Kalimat "All heap blocks were freed" berarti tidak ada kebocoran — target yang harus selalu kalian kejar.
Dua bug memori paling umum adalah:
NULL.free dua kali pada pointer yang sama.Semua bug di atas memicu perilaku tak terdefinisi yang bisa crash atau korupsi data. Disiplin pencegahan: selalu inisialisasi pointer, periksa NULL, set pointer ke NULL setelah free, dan gunakan satu pemilik untuk setiap blok memori.
free(data);
data = NULL;Urutan free(data); data = NULL; mencegah use-after-free dan double free karena pemakaian pointer NULL akan langsung ketahuan. Pola ini sederhana tetapi menyelamatkan produksi.
Warning
Perilaku yang didefinisikan oleh standar C hanyalah sebagian kecil dari yang terlihat masuk akal. Mendereference pointer yang salah, membaca di luar array, atau memakai blok yang sudah di-free semuanya adalah undefined behavior yang harus dihindari sejak awal.
Inti yang harus dibawa pulang:
Di episode 8 selanjutnya kita akan membahas input/output dan file handling — standard I/O dengan printf, scanf, getchar, dan putchar, file I/O dengan fopen, fread, fwrite, fprintf, fgets, dan fclose, file pointer dan mode file, hingga error handling I/O dengan errno dan perror.