Tidak semua fungsi perlu mengembalikan nilai. Fungsi void (dari kata Inggris void = “kosong”) adalah fungsi yang tidak memiliki return value—fungsi ini melakukan aksi, lalu selesai. Fungsi void cocok untuk tugas seperti mencetak output, memodifikasi struktur data melalui pointer, atau menjalankan efek samping tanpa perlu melaporkan hasil ke pemanggil. Pada chapter ini kita akan menelusuri ciri khas fungsi void, penggunaan early return dengan return;, serta peran void * sebagai pointer generik.

Karakteristik Fungsi void #

Fungsi void memiliki void sebagai return type. Body fungsi berjalan dari atas ke bawah; bila tidak ada return, fungsi selesai otomatis setelah statement terakhir dieksekusi. Karena tidak mengembalikan nilai, fungsi void tidak dapat dipakai dalam ekspresi aritmetika atau ditugaskan ke variabel.

c
#include <stdio.h>

/* Fungsi void: melakukan aksi tanpa mengembalikan nilai */
void cetak_header(const char *judul) {
    printf("=== %s ===\n", judul);
}

void cetak_garis(int panjang) {
    for (int i = 0; i < panjang; i++) {
        putchar('-');
    }
    putchar('\n');
}

void sapa_user(const char *nama) {
    if (nama == NULL) {
        printf("Halo, pengguna anonim\n");
        return;                  /* Early return dari void function */
    }
    printf("Halo, %s!\n", nama);
}

int main(void) {
    cetak_header("LAPORAN PENJUALAN");
    cetak_garis(25);
    sapa_user("Budi");
    sapa_user(NULL);
    return 0;
}

Output yang Dihasilkan:

text
=== LAPORAN PENJUALAN ===
-------------------------
Halo, Budi!
Halo, pengguna anonim

Mari kita telaah baris-baris kode di atas:

  1. Baris 4 (void cetak_header(const char *judul)): return type void menandakan fungsi ini tidak mengembalikan nilai. Parameter judul dibuat const char * karena fungsi hanya membaca string, tidak memodifikasinya.
  2. Baris 5 (printf("=== %s ===\n", judul);): body fungsi hanya mencetak teks. Setelah statement terakhir, fungsi otomatis selesai tanpa return.
  3. Baris 8 (void cetak_garis(int panjang)): fungsi void menerima int dan menggunakan loop untuk mencetak karakter - sebanyak panjang kali.
  4. Baris 15 (void sapa_user(const char *nama)): fungsi void dengan pola guard clause di awal.
  5. Baris 16 (if (nama == NULL)): pengecekan guard untuk argumen NULL.
  6. Baris 18 (return;): early return tanpa ekspresi. Statement ini keluar dari fungsi sapa_user segera, melewati printf di baris 20. Bentuk return; (tanpa nilai setelah return) adalah satu-satunya return yang valid di fungsi void.

Early Return di Fungsi void #

Walaupun fungsi void tidak mengembalikan nilai, statement return; (tanpa ekspresi) tetap berguna untuk keluar lebih awal. Pola ini disebut early return dan berguna untuk:

  • Validasi input: keluar bila argumen tidak valid (misalnya pointer NULL, panjang array 0, atau nilai di luar rentang).
  • Short-circuit logic: bila kondisi pertama sudah cukup untuk menentukan tidak ada yang perlu dilakukan, keluar segera tanpa mengeksekusi sisa body.

Pada contoh di atas, fungsi sapa_user memeriksa apakah nama == NULL. Bila ya, fungsi mencetak pesan anonim lalu keluar—tidak perlu memeriksa cabang lain. Pola ini membuat alur kode lebih datar dan mudah dibaca dibandingkan menumpuk if-else.

void *: Pointer Generik #

Tipe void * adalah pointer yang dapat menunjuk ke data tipe apa pun. Berbeda dengan int * atau char *, void * tidak memiliki informasi tipe—programmer bertanggung jawab meng-cast-nya ke tipe yang benar sebelum mengakses data. void * dipakai oleh fungsi generik seperti malloc (yang mengembalikan void *) dan qsort (yang menerima comparator dengan parameter const void *).

c
#include <stdio.h>

/* void* : pointer generik yang dapat menunjuk ke tipe apa pun */
void cetak_hex(const void *data, int n) {
    const unsigned char *p = (const unsigned char *)data;
    for (int i = 0; i < n; i++) {
        printf("%02x ", p[i]);
    }
    putchar('\n');
}

int main(void) {
    int angka = 0x12345678;
    double pi = 3.14;
    /* Fungsi void menerima pointer ke tipe apa pun */
    cetak_hex(&angka, sizeof(angka));
    cetak_hex(&pi, sizeof(pi));
    return 0;
}

Output yang Dihasilkan:

text
78 56 34 12 
1f 85 eb 51 b8 1e 09 40 

Pada contoh di atas, fungsi cetak_hex menerima const void *data (pointer ke data tipe apa pun) dan int n (jumlah byte). Di dalam body, data di-cast menjadi const unsigned char * agar dapat diakses byte-per-byte. Pemanggil main melewatkan &angka (alamat int) dan &pi (alamat double)—keduanya otomatis dikonversi ke void * tanpa cast eksplisit.

Hasil 78 56 34 12 adalah representasi byte dari int bernilai 0x12345678 pada sistem little-endian (byte paling tidak signifikan disimpan di alamat terendah). Hasil 1f 85 eb 51 b8 1e 09 40 adalah representasi byte dari double 3.14 dalam format IEEE 754. Contoh ini menunjukkan bahwa void * memungkinkan kita menulis fungsi yang bebas tipe—berguna untuk utilitas umum seperti hex dump.

void di Daftar Parameter #

Selain return type, kata kunci void juga dapat muncul di daftar parameter: void f(void). Bentuk ini secara eksplisit menyatakan bahwa fungsi tidak menerima parameter apa pun. Bandingkan dengan void f() (kurung kosong) yang dalam C berarti “fungsi dengan parameter tak ditentukan”—sebuah warisan gaya K&R yang sebaiknya dihindari. Selalu tulis void f(void) untuk fungsi tanpa parameter, dan tambahkan flag -Wstrict-prototypes saat kompilasi untuk menangkap pelanggaran.

Dengan pemahaman fungsi void, kita siap melangkah ke chapter Pass by Value untuk membahas bagaimana C melewatkan argument ke parameter—dan kenapa perubahan di dalam fungsi tidak memengaruhi variabel pemanggil.