Langsung ke konten
Belajar C

Panduan Lengkap Function dalam Bahasa C

Foto TaufiqOleh Taufiq
Function (Bahasa C)

Panduan Lengkap Function dalam Bahasa C

Function (fungsi) merupakan salah satu konsep fundamental dalam bahasa pemrograman C. Sebuah function berisi beberapa pernyataan yang dikemas dalam sebuah nama, sehingga bisa dipanggil berulang kali dari berbagai bagian program. Dalam panduan ini, kita akan membahas secara mendalam mulai dari sintaks dasar, cara passing parameter, tipe data pengembalian, scope variabel, hingga teknik lanjutan seperti rekursi dan alokasi memori.

Apa Itu Function dalam Bahasa C?

Secara sederhana, function adalah blok kode yang dapat dijalankan secara independen dan dipanggil kapan saja saat dibutuhkan. Menurut cppreference.com, fungsi dalam C didefinisikan dengan menyertakan tipe data pengembalian, nama fungsi, parameter-parameter (jika ada), dan badan fungsi dalam kurung kurawal.

Tujuan utama penggunaan function antara lain:

  1. Mempermudah pengembangan program — Program dibagi menjadi beberapa subprogram kecil, sehingga menjadi kunci dalam pembuatan program yang terstruktur.
  2. Menghemat ukuran program — Beberapa perintah yang sama dan dijalankan berulang kali bisa dikemas dalam satu fungsi, lalu dipanggil berkali-kali tanpa perlu menulis ulang kode yang sama.
  3. Meningkatkan keterbacaan kode — Dengan memberi nama yang deskriptif pada fungsi, kode menjadi lebih mudah dipahami oleh programmer lain.
  4. Memudahkan pemeliharaan (maintenance) — Jika ada perubahan logika, cukup ubah pada satu tempat saja.

Sintaks Dasar Deklarasi Function

Untuk mendeklarasikan sebuah fungsi dalam C, kita memerlukan prototype fungsi (dideklarasikan sebelum fungsi dipanggil) dan definisi fungsi (implementasi badan fungsi). Sintaks umumnya adalah:

Block Code Snippet Code
// Prototype fungsi
tipe_pengembalian nama_fungsi(tipe_param1 nama_param1, tipe_param2 nama_param2);

// Definisi fungsi
tipe_pengembalian nama_fungsi(tipe_param1 nama_param1, tipe_param2 nama_param2) {
 // badan fungsi
 return nilai_pengembalian; // jika tipe_pengembalian bukan void
}

Contoh prototype fungsi:

  • double kuadrat(int x);
  • float luas_segitiga(float alas, float tinggi);
  • int jumlah_bil(int x, int y, int z);

Jika fungsi tidak mengembalikan nilai, gunakan tipe void sebagai tipe pengembalian.

Contoh Function Lengkap: Menggambar Garis

Berikut adalah contoh fungsi sederhana untuk menggambar garis-garis dengan karakter -:

CSS Snippet CSS
#include <stdio.h>

void garis(void); // prototype fungsi

int main(void) {
 garis(); // panggil fungsi garis
 printf("NIM NAMA MAHASISWA\n");
 garis(); // panggil lagi
 printf("M0197001 AMIR HAMZAH\n");
 printf("M0197002 PAIMAN\n");
 garis();
 return 0;
}

void garis(void) { // definisi fungsi garis
 int i;
 for (i = 0; i <= 40; i++) {
 printf("-");
 }
 printf("\n");
}

Penjelasan baris per baris:

  • #include <stdio.h> — Menyertakan header standar untuk fungsi printf.
  • void garis(void); — Prototype fungsi. Menandakan bahwa garis tidak menerima parameter dan tidak mengembalikan nilai.
  • garis(); — Pemanggilan fungsi di dalam main. Eksekusi berpindah ke definisi garis.
  • for (i = 0; i <= 40; i++) — Perulangan yang mencetak karakter - sebanyak 41 kali.
  • return 0; — Mengembalikan nilai 0 ke sistem operasi, menandakan program berjalan sukses.

Contoh Function dengan Parameter dan Return Value

Berikut contoh fungsi yang menerima parameter dan mengembalikan nilai:

CSS Snippet CSS
#include <stdio.h>

float luas(float alas, float tinggi); // prototype

int main(void) {
 float a = 10.5f, t = 11.0f;
 printf("HITUNG LUAS SEGITIGA\n");
 printf("Panjang alas : %.2f\n", a);
 printf("Tinggi : %.2f\n", t);
 printf("Luasnya : %.2f\n", luas(a, t));
 return 0;
}

float luas(float alas, float tinggi) {
 float luas_segitiga = alas * tinggi / 2.0f;
 return luas_segitiga;
}

Penjelasan:

  • Fungsi luas menerima dua parameter bertipe float yaitu alas dan tinggi.
  • Di dalam fungsi, dihitung luas segitiga dengan rumus alas × tinggi / 2.
  • Nilai hasil perhitungan dikembalikan ke pemanggil dengan pernyataan return.

Passing Parameter: By Value vs By Reference (Pointer)

Salah satu konsep krusial dalam C adalah bagaimana parameter dikirim ke fungsi. C menggunakan dua metode utama:

1. Pass by Value (Perambatan Nilai)

Ketika parameter dikirim by value, salinan nilai asli dibuat. Perubahan pada parameter di dalam fungsi tidak mempengaruhi variabel asli di pemanggil.

CSS Snippet CSS
#include <stdio.h>

void ubah_nilai(int x) {
 x = 100; // hanya mengubah salinan lokal
 printf("Di dalam fungsi, x = %d\n", x);
}

int main(void) {
 int a = 10;
 ubah_nilai(a);
 printf("Di luar fungsi, a = %d\n", a); // tetap 10
 return 0;
}

// Output:
// Di dalam fungsi, x = 100
// Di luar fungsi, a = 10

Variabel x adalah salinan dari a. Ketika x diubah menjadi 100, a tetap bernilai 10.

2. Pass by Reference (Menggunakan Pointer)

Jika kita ingin mengubah nilai variabel asli dari dalam fungsi, kita mengirim alamat memori (pointer) dari variabel tersebut. Ini disebut pass by reference.

CSS Snippet CSS
#include <stdio.h>

void tukar(int *a, int *b) {
 int temp = *a;
 *a = *b;
 *b = temp;
}

int main(void) {
 int x = 5, y = 10;
 printf("Sebelum: x = %d, y = %d\n", x, y);
 tukar(&x, &y);
 printf("Sesudah: x = %d, y = %d\n", x, y);
 return 0;
}

// Output:
// Sebelum: x = 5, y = 10
// Sesudah: x = 10, y = 5

Penjelasan:

  • int *a, int *b — Parameter berupa pointer ke integer.
  • &x, &y — Operator & mengambil alamat memori dari variabel.
  • *a = *b — Dereference pointer untuk mengubah nilai di alamat memori yang ditunjuk.

Menggunakan pointer dalam C adalah kuncinya jika Anda perlu memodifikasi data di luar scope fungsi.

Return Type: Berbagai Tipe Data Pengembalian

Fungsi dalam C dapat mengembalikan berbagai tipe data, antara lain:

  • int — Bilangan bulat (contoh: int faktorial(int n))
  • float / double — Bilangan desimal
  • char — Satu karakter
  • void — Tidak mengembalikan nilai
  • struct — Struktur data kustom
  • pointer — Alamat memori

Contoh fungsi yang mengembalikan pointer:

CSS Snippet CSS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* salin_string(const char *sumber) {
 char *hasil = malloc(strlen(sumber) + 1);
 if (hasil != NULL) {
 strcpy(hasil, sumber);
 }
 return hasil;
}

int main(void) {
 char *teks = salin_string("Hello, C!");
 printf("%s\n", teks);
 free(teks); // jangan lupa bebaskan memori
 return 0;
}

Perhatikan bahwa kita menggunakan malloc untuk mengalokasikan memori secara dinamis, dan free untuk membebaskannya.

Scope Variabel: Lokal vs Global

Variabel Lokal

Variabel yang dideklarasikan di dalam fungsi hanya bisa diakses di dalam fungsi tersebut. Ini disebut variabel lokal atau automatic storage duration. Setelah fungsi selesai dieksekusi, memori untuk variabel lokal dibebaskan secara otomatis.

Block Code Snippet Code
void fungsi_a(void) {
 int x = 10; // hanya bisa diakses di sini
 printf("%d\n", x);
}

void fungsi_b(void) {
 // printf("%d\n", x); // ERROR! x tidak terlihat di sini
}

Variabel Global

Variabel yang dideklarasikan di luar semua fungsi bersifat global dan dapat diakses dari seluruh bagian program. Gunakan dengan bijak karena terlalu banyak variabel global membuat kode sulit dipelihara.

CSS Snippet CSS
#include <stdio.h>

int counter = 0; // variabel global

void tambah(void) {
 counter++; // mengakses variabel global
}

int main(void) {
 tambah();
 tambah();
 printf("Counter: %d\n", counter); // Counter: 2
 return 0;
}

Local Static Variables

Variabel lokal dengan kata kunci static mempertahankan nilainya antara pemanggilan fungsi:

CSS Snippet CSS
#include <stdio.h>

void hitung(void) {
 static int count = 0; // hanya diinisialisasi sekali
 count++;
 printf("Pemanggilan ke-%d\n", count);
}

int main(void) {
 hitung(); // Pemanggilan ke-1
 hitung(); // Pemanggilan ke-2
 hitung(); // Pemanggilan ke-3
 return 0;
}

Rekursi vs Iterasi

Dua pendekatan untuk menyelesaikan masalah berulang dalam C adalah rekursi dan iterasi (menggunakan loop).

Contoh Rekursi: Faktorial

CSS Snippet CSS
#include <stdio.h>

int faktorial(int n) {
 if (n <= 1) return 1; // basis rekursi
 return n * faktorial(n - 1); // panggilan rekursif
}

int main(void) {
 printf("5! = %d\n", faktorial(5)); // 5! = 120
 return 0;
}

Contoh Iterasi: Faktorial

CSS Snippet CSS
#include <stdio.h>

int faktorial_iter(int n) {
 int hasil = 1;
 for (int i = 2; i <= n; i++) {
 hasil *= i;
 }
 return hasil;
}

int main(void) {
 printf("5! = %d\n", faktorial_iter(5)); // 5! = 120
 return 0;
}

Perbandingan:

  • Rekursi lebih elegan untuk masalah dengan struktur rekursif alami (tree traversal, Fibonacci, divide-and-conquer). Namun, setiap panggilan rekursif menambah stack frame — terlalu banyak bisa menyebabkan stack overflow.
  • Iterasi umumnya lebih efisien secara memori karena tidak menambah kedalaman stack. Untuk masalah sederhana, iterasi sering kali lebih cepat.

Alokasi Memori dan Function

Ketika bekerja dengan fungsi yang mengelola data dalam jumlah besar, pemahaman tentang alokasi memori sangat penting:

CSS Snippet CSS
#include <stdio.h>
#include <stdlib.h>

int* buat_array(int ukuran) {
 int *arr = malloc(ukuran * sizeof(int));
 if (arr == NULL) {
 fprintf(stderr, "Gagal mengalokasikan memori\n");
 exit(EXIT_FAILURE);
 }
 for (int i = 0; i < ukuran; i++) {
 arr[i] = i * 10;
 }
 return arr;
}

int main(void) {
 int *data = buat_array(5);
 for (int i = 0; i < 5; i++) {
 printf("data[%d] = %d\n", i, data[i]);
 }
 free(data); // bebaskan memori setelah digunakan
 return 0;
}

Poin penting:

  • Gunakan malloc, calloc, atau realloc untuk alokasi memori dinamis (dokumentasi alokasi memori).
  • Selalu periksa apakah alokasi berhasil (nilai kembalian tidak NULL).
  • Setiap malloc harus diimbangi dengan free untuk menghindari memory leak.

Pitfall Umum dalam Penggunaan Function

  1. Lupa mendeklarasikan prototype — Jika fungsi dipanggil sebelum didefinisikan tanpa prototype, kompiler akan mengasumsikan tipe kembalian int, yang bisa menyebabkan bug tak terduga.
  2. Tidak memeriksa return value dari malloc — Jika alokasi memori gagal, mengakses pointer NULL menyebabkan segmentation fault.
  3. Returning address of local variable — Variabel lokal dihapus dari stack saat fungsi selesai. Mengembalikan alamatnya menyebabkan undefined behavior.
  4. Stack overflow dari rekursi tanpa basis — Pastikan setiap fungsi rekursif memiliki kondisi berhenti (base case).
  5. Shadowing variabel global — Jika parameter fungsi memiliki nama yang sama dengan variabel global, parameter akan menutupi (shadow) variabel global di dalam scope fungsi.

Best Practices untuk Penulisan Function

  • Buat fungsi tetap kecil dan fokus pada satu tugas (Single Responsibility Principle).
  • Gunakan nama fungsi yang deskriptif dan konsisten.
  • Sertakan komentar untuk menjelaskan tujuan fungsi, bukan implementasinya.
  • Hindari efek samping (side effects) yang tidak terduga — jika fungsi mengubah data global, dokumentasikan dengan jelas.
  • Gunakan const pada parameter yang tidak seharusnya diubah untuk kejelasan dan keamanan.
  • Manfaatkan static untuk membatasi visibilitas fungsi di dalam satu unit kompilasi (internal linkage).

Kesimpulan

Function adalah tulang punggung dari pemrograman struktural dalam C. Dengan memahami cara mendeklarasikan fungsi, passing parameter (baik by value maupun by reference melalui pointer), tipe data pengembalian, scope variabel, alokasi memori, serta perbandingan antara rekursi dan iterasi, Anda akan mampu menulis kode C yang bersih, efisien, dan mudah dipelihara.

Untuk referensi lebih lanjut, kunjungi cppreference.com — The C language reference dan dokumentasi C23 Draft Standard (N2310).

Hal yang sering ditanyakan seputar Panduan Lengkap Function dalam Bahasa C

Bagaimana cara mendeklarasikan dan mendefinisikan fungsi dalam bahasa C?

Deklarasi fungsi (prototype) ditulis sebelum fungsi dipanggil dengan format `tipe_pengembalian nama_fungsi(tipe_param nama_param);`. Definisi fungsi berisi implementasi badan fungsi dalam kurung kurawal setelah prototype. Prototype berfungsi sebagai pemberitahuan kepada compiler tentang signature fungsi sebelum dipanggil di dalam `main()`.

Apa bedanya pass by value dan pass by reference dalam fungsi C?

Pass by value mengirim salinan nilai parameter ke fungsi, sehingga perubahan di dalam fungsi tidak mempengaruhi variabel asli. Pass by reference dilakukan dengan mengirim pointer ke fungsi (menggunakan operator `&` saat pemanggilan dan `*` di dalam fungsi), sehingga perubahan langsung mempengaruhi variabel asli di memori.

Apa itu rekursi dalam fungsi C dan kapan sebaiknya digunakan?

Rekursi adalah teknik di mana fungsi memanggil dirinya sendiri untuk menyelesaikan masalah yang strukturnya berulang, seperti faktorial atau traversal tree. Rekursi efektif untuk masalah yang memiliki sub-problem identik dengan masalah utama, namun harus memiliki base case yang jelas agar tidak terjadi infinite recursion dan stack overflow.

Mengapa harus menggunakan fungsi dalam pemrograman C?

Fungsi membuat kode lebih terstruktur, mudah dibaca, dan hemat dari sisi ukuran program karena kode berulang tidak perlu ditulis ulang. Selain itu, pemeliharaan kode menjadi lebih mudah karena perubahan logika cukup dilakukan di satu tempat, yaitu di dalam definisi fungsi tersebut.

Apa itu scope variabel dalam konteks fungsi C?

Scope variabel menentukan area program di mana suatu variabel dapat diakses. Variabel lokal didefinisikan di dalam fungsi dan hanya bisa diakses di dalam fungsi tersebut. Variabel global didefinisikan di luar semua fungsi dan dapat diakses dari seluruh bagian program, meskipun penggunaannya berlebihan dapat menurunkan keterbacaan kode.

Komentar

Memuat komentar…

Tinggalkan Komentar

Alamat email Anda tidak akan dipublikasikan.