Variabel lokal biasa hidup hanya selama pemanggilan fungsi—setiap pemanggilan mendapatkan set variabel baru yang di-reset ke nilai awal. Tetapi kadang kita ingin sebuah variabel lokal mempertahankan nilainya antar pemanggilan fungsi, tanpa harus menjadikannya variabel global yang dapat diakses dari mana saja. Di sinilah peran static local variable: variabel yang scope-nya lokal (hanya terlihat di dalam fungsi), tetapi lifetime-nya statis (tetap hidup sepanjang program berjalan). Pada chapter ini kita akan menelusuri cara kerja static local variable, pola call counter, dan penggunaan static array untuk caching.

Karakteristik Static Local Variable #

Static local variable dideklarasikan dengan keyword static sebelum tipe variabel. Tiga sifat utamanya:

  1. Inisialisasi hanya sekali: pada pemanggilan pertama. Pemanggilan berikutnya tidak menginisialisasi ulang.
  2. Nilai tetap hidup antar pemanggilan: nilai variabel dipertahankan walaupun fungsi sudah selesai dieksekusi.
  3. Default zero initialization: bila tidak diberi inisialisasi eksplisit, variabel di-zero-initialize (sama seperti global).

Berikut contoh paling dasar: fungsi yang menghitung berapa kali ia dipanggil.

c
#include <stdio.h>

/* Static local variable: mempertahankan nilai antar pemanggilan */
int hitung_panggilan(void) {
    static int counter = 0;    /* Inisialisasi hanya sekali */
    counter++;
    return counter;
}

int main(void) {
    printf("Panggilan ke-1: %d\n", hitung_panggilan());
    printf("Panggilan ke-2: %d\n", hitung_panggilan());
    printf("Panggilan ke-3: %d\n", hitung_panggilan());
    printf("Panggilan ke-4: %d\n", hitung_panggilan());
    return 0;
}

Output yang Dihasilkan:

text
Panggilan ke-1: 1
Panggilan ke-2: 2
Panggilan ke-3: 3
Panggilan ke-4: 4

Mari kita telaah baris-baris kode di atas:

  1. Baris 4 (static int counter = 0;): deklarasi variabel lokal counter dengan keyword static. Inisialisasi = 0 hanya terjadi sekali—saat program dimulai (bukan saat fungsi dipanggil). Variabel counter tetap hidup sepanjang program berjalan.
  2. Baris 5 (counter++;): setiap kali hitung_panggilan dipanggil, nilai counter dinaikkan. Karena variabel tidak di-reset, nilainya terus bertambah: 0 → 1 → 2 → 3 → 4.
  3. Baris 6 (return counter;): nilai counter setelah inkremen dikembalikan ke pemanggil. Pemanggilan pertama mengembalikan 1, pemanggilan kedua mengembalikan 2, dan seterusnya.
  4. Baris 10-13 (pemanggilan berturut-turut): setiap pemanggilan hitung_panggilan() mengembalikan angka yang lebih besar, membuktikan bahwa counter tetap hidup antar pemanggilan.

Pola Umum: ID Generator dan Memoization #

Static local variable sangat berguna untuk dua pola: ID generator (menghasilkan ID unik yang monoton naik) dan memoization (menyimpan hasil komputasi untuk dipakai ulang).

c
#include <stdio.h>

/* Static local untuk ID generator unik */
int buat_id_baru(void) {
    static int id_berikutnya = 1000;   /* Dimulai dari 1000 */
    int id_sekarang = id_berikutnya;
    id_berikutnya++;
    return id_sekarang;
}

/* Static local untuk cache sederhana */
int fibonacci_memo(int n) {
    static int memo[20] = {0};        /* Default 0 untuk semua elemen */
    if (n < 1 || n > 19) return -1;
    if (n == 1 || n == 2) return 1;
    if (memo[n] != 0) return memo[n];  /* Sudah dihitung sebelumnya */
    memo[n] = fibonacci_memo(n - 1) + fibonacci_memo(n - 2);
    return memo[n];
}

int main(void) {
    printf("ID baru: %d\n", buat_id_baru());
    printf("ID baru: %d\n", buat_id_baru());
    printf("ID baru: %d\n", buat_id_baru());

    printf("Fib(10) = %d\n", fibonacci_memo(10));
    printf("Fib(15) = %d\n", fibonacci_memo(15));
    return 0;
}

Output yang Dihasilkan:

text
ID baru: 1000
ID baru: 1001
ID baru: 1002
Fib(10) = 55
Fib(15) = 610

Pada contoh di atas:

  • Fungsi buat_id_baru: variabel id_berikutnya adalah static local. Setiap pemanggilan mengembalikan ID saat ini (1000, 1001, 1002), lalu menaikkan counter. Pola ini umum di library yang menghasilkan ID unik (misalnya pengelolaan sesi atau object handle).
  • Fungsi fibonacci_memo: array memo[20] adalah static local array berisi 20 elemen, semuanya default 0. Saat fungsi dipanggil dengan n = 10, fungsi memeriksa memo[10]—bila sudah berisi nilai non-zero, fungsi mengembalikan nilai tersebut (cache hit). Bila masih 0, fungsi menghitung rekursif dan menyimpan hasilnya ke memo[n]. Pemanggilan fibonacci_memo(15) setelahnya dapat memanfaatkan hasil fibonacci_memo(10) yang sudah ada di cache—drastis mempercepat komputasi.

Static Const untuk Konstanta Lokal #

Sering kita ingin sebuah konstanta hanya terlihat di dalam fungsi tertentu, tanpa harus membuatnya global. Pola static const menggabungkan keuntungan static (inisisialisasi sekali, lifetime statis) dengan const (read-only, memungkinkan optimisasi compiler).

c
#include <stdio.h>

/* Static local: inisialisasi konstan hanya sekali */
double dapatkan_faktor_skala(void) {
    static const double skala = 0.85;   /* Inisialisasi sekali */
    return skala;
}

int main(void) {
    /* Walaupun dipanggil berkali-kali, skala tetap 0.85 */
    for (int i = 0; i < 3; i++) {
        printf("Skala pemanggilan %d: %.2f\n", i, dapatkan_faktor_skala());
    }
    return 0;
}

Output yang Dihasilkan:

text
Skala pemanggilan 0: 0.85
Skala pemanggilan 1: 0.85
Skala pemanggilan 2: 0.85

Pada contoh di atas, konstanta skala = 0.85 dideklarasikan sebagai static const double. Walaupun fungsi dapatkan_faktor_skala dipanggil tiga kali, konstanta tersebut tetap 0.85 karena static local hanya diinisialisasi sekali. Pendekatan ini lebih ringkas daripada mendeklarasikan konstanta global, dan tidak mencemari namespace file dengan nama skala yang hanya relevan untuk fungsi ini.

Dengan pemahaman static local, kita siap melangkah ke chapter Recursion untuk membahas pola pemanggilan diri sendiri—salah satu penggunaan fungsi yang paling elegan tetapi juga berbahaya bila tidak hati-hati.