Pointer parameter adalah solusi C untuk pass by reference: dengan melewatkan alamat variabel (bukan nilainya), fungsi dapat memodifikasi variabel pemanggil secara langsung. Pola ini sangat penting di C karena tidak ada reference type bawaan seperti di C++ atau Rust. Pada chapter ini kita akan menelusuri swap klasik sebagai contoh paling mendasar, pola output parameter untuk mengembalikan banyak nilai, serta pointer to pointer yang dipakai ketika kita ingin mengubah pointer pemanggil itu sendiri.
Swap Klasik dengan Pointer Parameter #
Contoh paling klasik penggunaan pointer parameter adalah fungsi tukar yang menukar nilai dua variabel pemanggil. Tanpa pointer, fungsi tukar(int a, int b) hanya akan menukar salinan lokal—variabel pemanggil tidak berubah. Dengan pointer, fungsi mengakses memori pemanggil secara langsung.
Visualisasi Konsep #
Diagram berikut memperlihatkan bagaimana pointer parameter memungkinkan fungsi tukar memodifikasi variabel pemanggil x dan y:
Pada diagram di atas, pemanggilan tukar(&x, &y) melewatkan alamat x dan y ke parameter pointer a dan b. Meskipun a dan b sendiri adalah salinan (pass by value), alamat yang disalin tetap menunjuk ke memori pemanggil. Saat fungsi melakukan *a = *b, penulisan terjadi di alamat x di stack frame main—bukan di salinan lokal. Inilah mengapa variabel pemanggil berubah: fungsi mengikuti alamat di pointer untuk menulis langsung ke memori pemanggil. Tanpa pointer, fungsi tukar(int a, int b) hanya akan menukar salinan lokal tanpa efek pada x dan y.
#include <stdio.h>
/* Swap klasik: menukar nilai dua variabel di pemanggil */
void tukar(int *a, int *b) {
int tmp = *a; /* Simpan nilai yang ditunjuk a */
*a = *b; /* Tulis nilai b ke alamat a */
*b = tmp; /* Tulis nilai tmp ke alamat b */
}
int main(void) {
int x = 5, y = 9;
printf("Sebelum: x = %d, y = %d\n", x, y);
tukar(&x, &y); /* Lewatkan alamat x dan y */
printf("Setelah: x = %d, y = %d\n", x, y);
return 0;
}Output yang Dihasilkan:
Sebelum: x = 5, y = 9
Setelah: x = 9, y = 5Mari kita telaah baris-baris kode di atas:
- Baris 4 (
void tukar(int *a, int *b)): parameteradanbadalah pointer keint. Saat fungsi dipanggil, alamat yang dilewatkan pemanggil disalin keadanb. - Baris 5 (
int tmp = *a;): dereferensi*amembaca nilaiintdi alamat yang disimpana. Nilai ini disimpan ke variabel lokaltmpsebagai cadangan sementara. - Baris 6 (
*a = *b;): dereferensi*a = ...menulis ke alamat yang ditunjuka. Nilai yang ditulis adalah*b(nilai di alamatb). Sekarang alamatxberisi nilai9(yang semula diy). - Baris 7 (
*b = tmp;): tulis nilaitmp(yang berisi nilai aslix = 5) ke alamat yang ditunjukb. Sekarang alamatyberisi5. - Baris 13 (
tukar(&x, &y);): operator&mengambil alamat variabelxdany. Alamat inilah yang dilewatkan sebagai argument, bukan nilaixdany.
Output Parameter untuk Banyak Nilai #
Pointer parameter sering dipakai untuk menulis hasil ke variabel pemanggil—pola ini disebut output parameter. Fungsi mengembalikan kode status via return, dan menulis hasil aktual ke memori yang ditunjuk pointer parameter. Pola ini memungkinkan satu fungsi mengembalikan beberapa nilai.
#include <stdio.h>
/* Mengisi nilai via pointer parameter (output parameter) */
int bagi(double a, double b, double *hasil, double *sisa) {
if (b == 0.0) {
return -1; /* Sinyal error */
}
*hasil = (int)(a / b); /* Bagian bulat */
*sisa = a - (*hasil * b); /* Sisa pembagian */
return 0; /* Sukses */
}
int main(void) {
double h, s;
int rc = bagi(17.0, 5.0, &h, &s);
if (rc == 0) {
printf("17 / 5 = %.0f, sisa = %.1f\n", h, s);
}
return 0;
}Output yang Dihasilkan:
17 / 5 = 3, sisa = 2.0Pada contoh di atas, fungsi bagi mengembalikan 0 bila sukses dan -1 bila gagal (pembagian dengan nol). Parameter hasil dan sisa adalah output parameter—pointer yang akan ditulis fungsi dengan hasil bagi dan sisa. Pemanggil main menyediakan variabel h dan s, lalu melewatkan alamatnya (&h, &s). Setelah pemanggilan sukses, h berisi 3.0 dan s berisi 2.0. Pola ini sangat umum di API C seperti strtod (yang mengembalikan double sekaligus menulis posisi akhir parsing melalui char **endptr).
Pointer to Pointer #
Kadang kita ingin fungsi mengubah pointer pemanggil itu sendiri—bukan nilai yang ditunjuk pointer. Contoh paling umum adalah fungsi alokasi: fungsi mengalokasikan memori secara internal dan ingin menulis pointer hasil alokasi ke variabel pointer pemanggil. Untuk ini, kita perlu melewatkan pointer ke pointer (int **).
#include <stdio.h>
/* Alokasi memori lewat pointer-to-pointer */
#include <stdlib.h>
int alokasi_buffer(int **pp, int n) {
int *p = malloc((size_t)n * sizeof(int));
if (p == NULL) {
return -1; /* Gagal alokasi */
}
for (int i = 0; i < n; i++) {
p[i] = i * 10;
}
*pp = p; /* Tulis pointer ke pointer pemanggil */
return 0; /* Sukses */
}
int main(void) {
int *data = NULL;
int rc = alokasi_buffer(&data, 5); /* Lewatkan alamat data */
if (rc == 0) {
for (int i = 0; i < 5; i++) {
printf("data[%d] = %d\n", i, data[i]);
}
free(data);
} else {
printf("Alokasi gagal\n");
}
return 0;
}Output yang Dihasilkan:
data[0] = 0
data[1] = 10
data[2] = 20
data[3] = 30
data[4] = 40Pada contoh di atas, parameter pp bertipe int ** (pointer ke pointer ke int). Pemanggil melewatkan &data (alamat variabel pointer data). Di dalam fungsi, *pp = p; menulis pointer hasil malloc ke variabel data di pemanggil—bukan hanya ke salinan lokal. Setelah pemanggilan sukses, data di main menunjuk ke buffer yang baru dialokasikan. Pola ini populer di C untuk fungsi yang mengalokasikan buffer dan ingin mengembalikan pointer tersebut ke pemanggil sambil tetap memberi kode status via return value.
Konstkorrekt: const pada Pointer Parameter #
Untuk pointer parameter yang hanya membaca data (tidak memodifikasi), tambahkan const pada tipe yang ditunjuk. Misalnya void cetak_array(const int *arr, int n) memberitahu compiler dan pembaca bahwa fungsi tidak akan mengubah elemen array. Kwalifier const juga memungkinkan pemanggil melewatkan array const tanpa cast eksplisit—mengaktifkan type checking yang lebih ketat. Biasakan selalu menambah const pada pointer parameter yang tidak dimaksudkan untuk memodifikasi data yang ditunjuk.
Pointer parameter adalah jembatan antara fungsi dan variabel pemanggil di C. Dengan memahami swap, output parameter, dan pointer-to-pointer, kita siap melangkah ke chapter Scope Variabel untuk membahas di mana sebuah variabel “terlihat” di dalam program.