Python

βš™οΈ C Programming untuk Pemula: Panduan Lengkap

Tutorial lengkap belajar C Programming dari nol β€” variabel, tipe data, pointer, array, fungsi, struct, file I/O, dan quiz interaktif dengan contoh kode praktis

1. Pengenalan C Programming

C adalah bahasa pemrograman general-purpose yang dikembangkan oleh Dennis Ritchie di Bell Labs pada tahun 1972. C merupakan salah satu bahasa pemrograman yang paling berpengaruh dalam sejarah komputer dan menjadi dasar bagi banyak bahasa modern seperti C++, Java, C#, dan Python.

C dirancang sebagai bahasa tingkat menengah yang menggabungkan kemampuan bahasa tingkat rendah (hardware access) dengan fitur bahasa tingkat tinggi (structured programming). C digunakan secara luas di sistem operasi (Linux, Windows kernel), embedded systems, game engines, compiler, dan berbagai aplikasi high-performance.

Mengapa Belajar C?

Keunggulan Penjelasan
Sangat CepatC menghasilkan kode mesin yang sangat efisien, cocok untuk aplikasi yang membutuhkan performa tinggi
Low-Level AccessBisa langsung memanipulasi memori melalui pointer dan alamat memori
PortabelKode C bisa dikompilasi dan dijalankan di hampir semua platform
FoundationMemahami C membantu memahami bahasa lain seperti C++, Java, Rust
Embedded SystemsMenjadi bahasa utama untuk mikrokontroler, IoT, dan sistem embedded
Operating SystemsKernel Linux, Windows, dan macOS ditulis dengan C

C vs Bahasa Lain

Aspek C Python Java
TipeCompiledInterpretedCompiled + JIT
TypingStaticDynamicStatic
Kecepatan🟒 Sangat Cepat🟑 Sedang🟒 Cepat
MemoryManualGarbage CollectionGarbage Collection
Sintaks🟑 Sedang🟒 Sangat MudahπŸ”΄ Verbose
Cocok untukSystem, EmbeddedAI, Data, OtomasiEnterprise, Android
Diagram: Proses Kompilasi C
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              PROSES KOMPILASI C PROGRAM                  β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Source    β”‚    β”‚ Pre-     β”‚    β”‚  Compiler        β”‚  β”‚
β”‚  β”‚ Code     │───▢│ Processor│───▢│  (Translate to   β”‚  β”‚
β”‚  β”‚ .c file  β”‚    β”‚ (#includeβ”‚    β”‚   Assembly)      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  #define)β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚             β”‚
β”‚                                           β–Ό             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Executable│◀──│ Linker   │◀──│  Assembler       β”‚  β”‚
β”‚  β”‚ Program  β”‚    β”‚ (Combine β”‚    β”‚  (Object Code    β”‚  β”‚
β”‚  β”‚ (.exe)   β”‚    β”‚  libs)   β”‚    β”‚   .o / .obj)     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Instalasi dan Setup

Untuk memulai programming C, Anda membutuhkan compiler. GCC (GNU Compiler Collection) adalah compiler C yang paling populer dan tersedia di semua platform.

Instalasi di Windows

Windows
# Opsi 1: MinGW-w64 (GCC untuk Windows)
# 1. Download dari https://www.mingw-w64.org/
# 2. Instal dan tambahkan ke PATH
# 3. Verifikasi:
gcc --version

# Opsi 2: MSYS2 (recommended)
# 1. Download dari https://www.mys2.org/
# 2. Instal, buka MSYS2 terminal:
pacman -S mingw-w64-x86_64-gcc
# 3. Tambahkan C:\msys64\mingw64\bin ke PATH

# Opsi 3: WSL (Windows Subsystem for Linux)
wsl --install
# Di dalam WSL:
sudo apt install gcc build-essential -y

Instalasi di Linux

Linux (Ubuntu/Debian)
# Instal GCC dan build tools
sudo apt update
sudo apt install gcc build-essential gdb -y

# Verifikasi
gcc --version
# Output: gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0

# Instal editor/code editor
# VS Code (recommended):
sudo snap install code --classic
# Atau vim:
sudo apt install vim -y

Program C Pertama

C β€” hello.c
#include <stdio.h>

int main() {
    printf("Halo, dunia!\n");
    printf("Selamat datang di C Programming!\n");
    printf("Belajar C di BeebaneLabs\n");
    return 0;
}

// Kompilasi dan jalankan:
// gcc hello.c -o hello
// ./hello
//
// Output:
// Halo, dunia!
// Selamat datang di C Programming!
// Belajar C di BeebaneLabs

Anatomy Program C

C β€” Struktur Dasar
// 1. Preprocessor directives β€” diawali dengan #
#include <stdio.h>    // Library standar input/output
#include <stdlib.h>   // Library standar (malloc, exit, dll)

// 2. Deklarasi fungsi (opsional, untuk forward declaration)
int tambah(int a, int b);

// 3. Fungsi main β€” titik awal eksekusi program
int main(int argc, char *argv[]) {
    // Kode program Anda di sini
    int hasil = tambah(5, 3);
    printf("5 + 3 = %d\n", hasil);
    return 0;  // 0 = program berhasil
}

// 4. Definisi fungsi
int tambah(int a, int b) {
    return a + b;
}
πŸ’‘ Tips

Selalu akhiri setiap statement dengan titik koma (;). Gunakan \n di akhir printf() untuk pindah baris. Jangan lupa return 0; di akhir fungsi main() untuk menandakan program berakhir dengan sukses.

3. Variabel dan Tipe Data

Di C, setiap variabel harus dideklarasikan dengan tipe data secara eksplisit sebelum digunakan. Ini berbeda dengan Python yang menggunakan dynamic typing.

Tipe Data Dasar

Tipe Ukuran Rentang Contoh
char1 byte-128 s/d 127'A', 'z', '\n'
int4 byte-2.1 miliar s/d 2.1 miliar42, -10, 0
float4 byteΒ±3.4 Γ— 10^383.14f, -0.5f
double8 byteΒ±1.7 Γ— 10^3083.14159265358979
short2 byte-32768 s/d 32767100, -50
long8 byteΒ±9.2 Γ— 10^181234567890L
unsigned int4 byte0 s/d 4.2 miliar42U

Deklarasi dan Inisialisasi Variabel

C β€” Variabel
#include <stdio.h>
#include <string.h>

int main() {
    // Deklarasi variabel
    int umur = 25;
    float tinggi = 175.5;
    char grade = 'A';
    double pi = 3.14159265358979;

    // Deklarasi string (array of char)
    char nama[50] = "Budi Santoso";

    // Multiple declaration
    int a = 10, b = 20, c = 30;

    // Konstanta β€” tidak bisa diubah
    const int MAKS_PESERTA = 100;
    #define PI 3.14159  // Preprocessor constant

    // sizeof β€” cek ukuran tipe data
    printf("Ukuran int: %lu byte\n", sizeof(int));
    printf("Ukuran float: %lu byte\n", sizeof(float));
    printf("Ukuran double: %lu byte\n", sizeof(double));
    printf("Ukuran char: %lu byte\n", sizeof(char));

    // Menampilkan nilai
    printf("Nama: %s\n", nama);
    printf("Umur: %d tahun\n", umur);
    printf("Tinggi: %.1f cm\n", tinggi);
    printf("Grade: %c\n", grade);
    printf("Pi: %.15f\n", pi);

    // Format specifier umum:
    // %d = integer, %f = float/double, %c = char
    // %s = string, %x = hexadecimal, %o = octal
    // %p = pointer address, %lu = unsigned long

    return 0;
}

Operator di C

C β€” Operator
#include <stdio.h>

int main() {
    int a = 15, b = 4;

    // Aritmatika
    printf("a + b = %d\n", a + b);   // 19
    printf("a - b = %d\n", a - b);   // 11
    printf("a * b = %d\n", a * b);   // 60
    printf("a / b = %d\n", a / b);   // 3 (integer division!)
    printf("a %% b = %d\n", a % b);  // 3 (modulus)

    // Perbandingan β€” menghasilkan 0 (false) atau 1 (true)
    printf("a == b: %d\n", a == b);  // 0
    printf("a != b: %d\n", a != b);  // 1
    printf("a > b: %d\n", a > b);   // 1

    // Logika
    // && (AND), || (OR), ! (NOT)
    printf("AND: %d\n", (a > 10 && b > 2));  // 1
    printf("OR: %d\n", (a > 20 || b > 2));   // 1

    // Increment/Decrement
    int x = 10;
    x++;    // x sekarang 11
    x--;    // x kembali 10
    ++x;    // x = 11 (prefix)
    printf("x = %d\n", x);  // 11

    // Bitwise operator
    int p = 5;  // 0101
    int q = 3;  // 0011
    printf("p & q = %d\n", p & q);   // 1  (0001)
    printf("p | q = %d\n", p | q);   // 7  (0111)
    printf("p ^ q = %d\n", p ^ q);   // 6  (0110)
    printf("p << 1 = %d\n", p << 1); // 10 (1010)

    return 0;
}

4. Pointer

Pointer adalah salah satu fitur paling powerful dan penting di C. Pointer menyimpan alamat memori dari variabel lain, bukan nilainya. Memahami pointer adalah kunci untuk menguasai C.

Diagram: Cara Kerja Pointer
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  CARA KERJA POINTER                 β”‚
β”‚                                                     β”‚
β”‚  Variabel 'x'          Pointer 'ptr'               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚  β”‚ nilai: 42  β”‚        β”‚ alamat:    │──────┐       β”‚
β”‚  β”‚ addr: 0x100│◀───────│ 0x100     β”‚      β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚       β”‚
β”‚                                            β”‚       β”‚
β”‚  int x = 42;              int *ptr = &x;   β”‚       β”‚
β”‚  printf("%d", x);         printf("%d", *ptrβ”‚);     β”‚
β”‚  // Output: 42            // Output: 42    β”‚       β”‚
β”‚                                            β–Ό       β”‚
β”‚  ptr menyimpan alamat x (0x100),           β”‚       β”‚
β”‚  *ptr mengakses nilai di alamat tersebut   β”‚       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Dasar Pointer

C β€” Pointer Dasar
#include <stdio.h>

int main() {
    int x = 42;
    int *ptr = &x;  // ptr menyimpan alamat x

    // & (address-of) β€” mendapatkan alamat variabel
    // * (dereference) β€” mendapatkan nilai dari alamat

    printf("Nilai x: %d\n", x);           // 42
    printf("Alamat x: %p\n", (void*)&x);   // 0x7ffd...
    printf("Nilai ptr (alamat): %p\n", (void*)ptr); // sama
    printf("Nilai *ptr: %d\n", *ptr);      // 42

    // Mengubah nilai melalui pointer
    *ptr = 100;
    printf("x setelah diubah via pointer: %d\n", x); // 100

    // Pointer ke pointer
    int **pptr = &ptr;
    printf("**pptr = %d\n", **pptr);  // 100

    // Pointer NULL
    int *null_ptr = NULL;
    if (null_ptr == NULL) {
        printf("Pointer ini tidak menunjuk ke mana-mana\n");
    }

    return 0;
}

Pointer dan Fungsi (Pass by Reference)

C β€” Pointer ke Fungsi
#include <stdio.h>

// Pass by value β€” tidak mengubah variabel asli
void tukar_salah(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    // Perubahan hanya di dalam fungsi ini!
}

// Pass by reference (via pointer) β€” MENGUBAH variabel asli
void tukar_benar(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
    // Perubahan langsung ke alamat memori asli!
}

// Fungsi yang mengembalikan beberapa nilai via pointer
void hitung(int a, int b, int *hasil_tambah, int *hasil_kali) {
    *hasil_tambah = a + b;
    *hasil_kali = a * b;
}

int main() {
    int x = 10, y = 20;

    printf("Sebelum tukar: x=%d, y=%d\n", x, y);
    tukar_salah(x, y);
    printf("Setelah tukar_salah: x=%d, y=%d\n", x, y); // Tidak berubah!

    tukar_benar(&x, &y);
    printf("Setelah tukar_benar: x=%d, y=%d\n", x, y); // Berubah!

    int tambah, kali;
    hitung(5, 3, &tambah, &kali);
    printf("5+3=%d, 5*3=%d\n", tambah, kali);

    return 0;
}
⚠️ Peringatan

Pointer yang tidak diinisialisasi (dangling pointer) dan pointer yang sudah di-free tapi masih dipakai (use-after-free) adalah sumber bug yang paling berbahaya di C. Selalu inisialisasi pointer ke NULL dan set ke NULL setelah free().

5. Array dan String

Array adalah kumpulan elemen dengan tipe data yang sama yang disimpan secara berurutan di memori. Di C, array memiliki ukuran tetap yang ditentukan saat deklarasi.

Array Satu Dimensi

C β€” Array 1D
#include <stdio.h>

int main() {
    // Deklarasi array
    int nilai[5] = {90, 85, 78, 92, 88};
    int angka[10] = {0};  // Semua elemen = 0
    int arr[5];            // Uninitialized (bahaya!)

    // Mengakses elemen (index dimulai dari 0)
    printf("Nilai ke-0: %d\n", nilai[0]);  // 90
    printf("Nilai ke-3: %d\n", nilai[3]);  // 92

    // Mengubah elemen
    nilai[2] = 95;

    // Loop melalui array
    int jumlah = 0;
    for (int i = 0; i < 5; i++) {
        printf("nilai[%d] = %d\n", i, nilai[i]);
        jumlah += nilai[i];
    }
    printf("Rata-rata: %.2f\n", jumlah / 5.0);

    // Ukuran array
    printf("Jumlah elemen: %lu\n", sizeof(nilai) / sizeof(nilai[0]));

    // Array dan pointer β€” nama array adalah pointer ke elemen pertama
    printf("Alamat array: %p\n", (void*)nilai);
    printf("Alamat elemen[0]: %p\n", (void*)&nilai[0]);
    printf("Nilai via pointer: %d\n", *nilai);        // 90
    printf("Nilai via pointer+2: %d\n", *(nilai + 2)); // 95

    return 0;
}

Array Dua Dimensi (Matrix)

C β€” Array 2D
#include <stdio.h>

int main() {
    // Matrix 3x3
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    // Menampilkan matrix
    printf("Matrix 3x3:\n");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    // Transpose matrix
    int transpose[3][3];
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            transpose[j][i] = matrix[i][j];
        }
    }

    printf("\nTranspose:\n");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", transpose[i][j]);
        }
        printf("\n");
    }

    return 0;
}

String di C

C β€” String
#include <stdio.h>
#include <string.h>

int main() {
    // String = array of char yang diakhiri null terminator '\0'
    char nama[] = "Budi";            // Ukuran otomatis: 5 (4 + '\0')
    char kota[50] = "Jakarta";       // Ukuran 50, isi "Jakarta\0"

    // Fungsi string dari string.h
    printf("Panjang nama: %lu\n", strlen(nama));  // 4

    // strcpy β€” menyalin string
    char salinan[50];
    strcpy(salinan, nama);
    printf("Salinan: %s\n", salinan);

    // strcat β€” menggabungkan string
    char greeting[100] = "Halo, ";
    strcat(greeting, nama);
    strcat(greeting, "!");
    printf("%s\n", greeting);  // Halo, Budi!

    // strcmp β€” membandingkan string
    // return 0 jika sama, <0 jika str1 < str2, >0 jika str1 > str2
    printf("strcmp: %d\n", strcmp("apel", "jeruk"));  // negatif

    // sprintf β€” menulis ke string (bukan ke layar)
    char buffer[200];
    sprintf(buffer, "Nama: %s, Umur: %d, Kota: %s", nama, 25, kota);
    printf("%s\n", buffer);

    // Input string dari user
    char input[100];
    printf("Masukkan nama: ");
    fgets(input, sizeof(input), stdin);  // Lebih aman dari gets()
    input[strcspn(input, "\n")] = 0;     // Hapus newline
    printf("Hello, %s!\n", input);

    return 0;
}

6. Fungsi

Fungsi adalah blok kode yang bisa dipanggil berulang kali. Fungsi membantu memecah program menjadi bagian-bagian kecil yang reusable dan mudah di-maintain.

Definisi dan Pemanggilan Fungsi

C β€” Fungsi
#include <stdio.h>
#include <math.h>

// Fungsi tanpa return (void)
void sapa(char nama[]) {
    printf("Halo, %s! Selamat datang.\n", nama);
}

// Fungsi dengan return value
int tambah(int a, int b) {
    return a + b;
}

// Fungsi dengan banyak parameter
float hitung_rata(int nilai[], int jumlah) {
    int total = 0;
    for (int i = 0; i < jumlah; i++) {
        total += nilai[i];
    }
    return (float)total / jumlah;
}

// Rekursif β€” fungsi yang memanggil dirinya sendiri
long faktorial(int n) {
    if (n <= 1) return 1;       // Base case
    return n * faktorial(n - 1); // Recursive case
}

// Fungsi rekursif β€” Fibonacci
int fibonacci(int n) {
    if (n <= 0) return 0;
    if (n == 1) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// Function pointer β€” menyimpan alamat fungsi
int operasi(int a, int b, int (*func)(int, int)) {
    return func(a, b);
}

int kali(int a, int b) { return a * b; }
int bagi(int a, int b) { return b != 0 ? a / b : 0; }

int main() {
    sapa("Budi");

    int hasil = tambah(10, 20);
    printf("10 + 20 = %d\n", hasil);

    int data[] = {80, 90, 75, 85, 95};
    printf("Rata-rata: %.2f\n", hitung_rata(data, 5));

    printf("Faktorial 5! = %ld\n", faktorial(5));  // 120
    printf("Fibonacci(10) = %d\n", fibonacci(10));  // 55

    // Function pointer
    printf("3 * 4 = %d\n", operasi(3, 4, kali));
    printf("10 / 3 = %d\n", operasi(10, 3, bagi));

    return 0;
}
πŸ’‘ Tips Rekursi

Setiap fungsi rekursif harus memiliki base case (kondisi berhenti) untuk mencegah infinite recursion. Terlalu dalam rekursi bisa menyebabkan stack overflow. Untuk kasus sederhana, pertimbangkan menggunakan iterasi (loop) sebagai alternatif yang lebih efisien.

7. Struct dan Union

Struct adalah tipe data yang memungkinkan Anda mengelompokkan beberapa variabel dengan tipe berbeda menjadi satu kesatuan. Struct adalah cikal bakal dari class di C++.

Struct Dasar

C β€” Struct
#include <stdio.h>
#include <string.h>

// Definisi struct
struct Mahasiswa {
    char nama[50];
    int umur;
    float ipk;
    char jurusan[50];
};

// Struct dengan typedef β€” tidak perlu 'struct' lagi
typedef struct {
    float x;
    float y;
} Titik;

typedef struct {
    Titik posisi;
    float radius;
} Lingkaran;

// Fungsi yang menerima struct
void cetak_mahasiswa(struct Mahasiswa m) {
    printf("Nama    : %s\n", m.nama);
    printf("Umur    : %d tahun\n", m.umur);
    printf("IPK     : %.2f\n", m.ipk);
    printf("Jurusan : %s\n", m.jurusan);
}

// Fungsi dengan pointer ke struct (lebih efisien)
void ubah_ipk(struct Mahasiswa *m, float ipk_baru) {
    m->ipk = ipk_baru;  // Arrow operator untuk pointer
}

int main() {
    // Membuat instance struct
    struct Mahasiswa mhs1;
    strcpy(mhs1.nama, "Budi Santoso");
    mhs1.umur = 20;
    mhs1.ipk = 3.75;
    strcpy(mhs1.jurusan, "Teknik Informatika");

    cetak_mahasiswa(mhs1);

    // Struct initialization
    struct Mahasiswa mhs2 = {"Ani Putri", 21, 3.90, "Sistem Informasi"};
    printf("\n--- Mahasiswa 2 ---\n");
    cetak_mahasiswa(mhs2);

    // Pointer ke struct
    struct Mahasiswa *ptr = &mhs1;
    printf("\nAkses via pointer: %s\n", ptr->nama);
    ubah_ipk(&mhs1, 3.85);
    printf("IPK baru: %.2f\n", mhs1.ipk);

    // Array of struct
    struct Mahasiswa kelas[3] = {
        {"Andi", 19, 3.50, "DKV"},
        {"Sari", 20, 3.80, "Akuntansi"},
        {"Dedi", 21, 3.65, "Hukum"}
    };

    printf("\n--- Daftar Kelas ---\n");
    for (int i = 0; i < 3; i++) {
        printf("%d. %s (IPK: %.2f)\n", i+1, kelas[i].nama, kelas[i].ipk);
    }

    // Typedef struct
    Titik p1 = {3.0, 4.0};
    Lingkaran c1 = {{0.0, 0.0}, 5.0};
    printf("\nTitik: (%.1f, %.1f)\n", p1.x, p1.y);
    printf("Lingkaran: pusat(%.1f,%.1f) r=%.1f\n",
           c1.posisi.x, c1.posisi.y, c1.radius);

    return 0;
}

Enum dan Bit Field

C β€” Enum
#include <stdio.h>

// Enum β€” tipe data dengan nilai bernama
enum Hari { SENIN, SELASA, RABU, KAMIS, JUMAT, SABTU, MINGGU };
// SENIN=0, SELASA=1, dst.

enum Status { AKTIF = 1, NONAKTIF = 0, SUSPEND = -1 };

// Bit field β€” menghemat memori untuk flag boolean
struct Flags {
    unsigned int is_active   : 1;  // 1 bit
    unsigned int is_admin    : 1;  // 1 bit
    unsigned int level       : 3;  // 3 bit (0-7)
    unsigned int reserved    : 3;  // 3 bit
};

int main() {
    enum Hari hari_ini = RABU;
    printf("Hari ke-%d\n", hari_ini);  // 2

    switch (hari_ini) {
        case SENIN: case SELASA: case RABU:
        case KAMIS: case JUMAT:
            printf("Hari kerja\n");
            break;
        case SABTU: case MINGGU:
            printf("Weekend!\n");
            break;
    }

    struct Flags f = {1, 1, 5, 0};
    printf("Active: %u, Admin: %u, Level: %u\n",
           f.is_active, f.is_admin, f.level);
    printf("Ukuran struct Flags: %lu byte\n", sizeof(struct Flags));

    return 0;
}

8. Kontrol Alur

Kontrol alur menentukan jalannya eksekusi program berdasarkan kondisi atau pengulangan.

If-Else dan Switch

C β€” If-Else & Switch
#include <stdio.h>

int main() {
    int nilai = 85;

    // If-else if-else
    if (nilai >= 90) {
        printf("Grade: A\n");
    } else if (nilai >= 80) {
        printf("Grade: B\n");
    } else if (nilai >= 70) {
        printf("Grade: C\n");
    } else if (nilai >= 60) {
        printf("Grade: D\n");
    } else {
        printf("Grade: E\n");
    }

    // Ternary operator
    char *status = (nilai >= 60) ? "Lulus" : "Tidak Lulus";
    printf("Status: %s\n", status);

    // Switch-case
    int hari = 3;
    switch (hari) {
        case 1: printf("Senin\n"); break;
        case 2: printf("Selasa\n"); break;
        case 3: printf("Rabu\n"); break;
        case 4: printf("Kamis\n"); break;
        case 5: printf("Jumat\n"); break;
        default: printf("Weekend\n"); break;
    }

    return 0;
}

Loop (Perulangan)

C β€” Loop
#include <stdio.h>

int main() {
    // For loop
    printf("For loop: ");
    for (int i = 1; i <= 5; i++) {
        printf("%d ", i);
    }
    printf("\n");

    // While loop
    printf("While loop: ");
    int j = 1;
    while (j <= 5) {
        printf("%d ", j);
        j++;
    }
    printf("\n");

    // Do-while loop β€” minimal dieksekusi 1x
    printf("Do-while: ");
    int k = 10;
    do {
        printf("%d ", k);
        k++;
    } while (k <= 5);  // Tetap cetak 10 sekali
    printf("\n");

    // Nested loop β€” membuat pola bintang
    printf("\nPola segitiga:\n");
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= i; j++) {
            printf("* ");
        }
        printf("\n");
    }

    // Break dan Continue
    printf("\nAngka ganjil (1-10): ");
    for (int i = 1; i <= 10; i++) {
        if (i % 2 == 0) continue;  // Skip genap
        printf("%d ", i);
    }
    printf("\n");

    // Infinite loop dengan break
    int count = 0;
    while (1) {
        if (count >= 5) break;
        printf("Iterasi %d\n", count);
        count++;
    }

    // Goto (hindari penggunaan kecuali sangat perlu)
    goto selesai;
    printf("Ini tidak akan dieksekusi\n");
    selesai:
    printf("Program selesai!\n");

    return 0;
}

9. File I/O

C menyediakan fungsi-fungsi untuk membaca dan menulis file melalui library stdio.h. File I/O sangat penting untuk menyimpan data secara persisten.

Menulis dan Membaca File Teks

C β€” File I/O
#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *fp;

    // ===== MENULIS FILE =====
    fp = fopen("data.txt", "w");  // "w" = write (overwrite)
    if (fp == NULL) {
        printf("Error: Tidak bisa membuka file!\n");
        return 1;
    }

    fprintf(fp, "Nama: Budi Santoso\n");
    fprintf(fp, "Umur: 25\n");
    fprintf(fp, "IPK: 3.75\n");
    fclose(fp);
    printf("File berhasil ditulis!\n");

    // ===== APPEND (menambah di akhir) =====
    fp = fopen("data.txt", "a");  // "a" = append
    if (fp != NULL) {
        fprintf(fp, "Jurusan: Teknik Informatika\n");
        fclose(fp);
    }

    // ===== MEMBACA FILE =====
    // Cara 1: fgets β€” baca baris per baris
    fp = fopen("data.txt", "r");  // "r" = read
    if (fp == NULL) {
        printf("Error: File tidak ditemukan!\n");
        return 1;
    }

    char buffer[256];
    printf("\n=== Isi File ===\n");
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf("%s", buffer);
    }
    fclose(fp);

    // Cara 2: fscanf β€” baca dengan format
    fp = fopen("data.txt", "r");
    if (fp != NULL) {
        char nama[50], jurusan[50];
        int umur;
        float ipk;

        // Skip "Nama: ", baca nama
        fscanf(fp, "Nama: %[^\n]\n", nama);
        fscanf(fp, "Umur: %d\n", &umur);
        fscanf(fp, "IPK: %f\n", &ipk);
        fscanf(fp, "Jurusan: %[^\n]\n", jurusan);

        printf("\nParsed: %s, %d, %.2f, %s\n", nama, umur, ipk, jurusan);
        fclose(fp);
    }

    // ===== MODE FILE =====
    // "r"  β€” read only
    // "w"  β€” write only (overwrite, buat baru jika tidak ada)
    // "a"  β€” append (tambah di akhir)
    // "r+" β€” read + write
    // "w+" β€” read + write (overwrite)
    // "a+" β€” read + append

    return 0;
}

File Binary

C β€” Binary File I/O
#include <stdio.h>
#include <string.h>

typedef struct {
    char nama[50];
    int umur;
    float ipk;
} Mahasiswa;

int main() {
    // Menulis struct ke file binary
    Mahasiswa data[] = {
        {"Budi", 20, 3.75},
        {"Ani", 21, 3.90},
        {"Dedi", 19, 3.50}
    };

    FILE *fp = fopen("mahasiswa.bin", "wb");  // wb = write binary
    if (fp == NULL) return 1;

    // Tulis jumlah data dulu
    int jumlah = 3;
    fwrite(&jumlah, sizeof(int), 1, fp);

    // Tulis array struct
    fwrite(data, sizeof(Mahasiswa), jumlah, fp);
    fclose(fp);
    printf("Data binary berhasil ditulis!\n");

    // Membaca struct dari file binary
    fp = fopen("mahasiswa.bin", "rb");  // rb = read binary
    if (fp == NULL) return 1;

    int count;
    fread(&count, sizeof(int), 1, fp);

    Mahasiswa hasil[count];
    fread(hasil, sizeof(Mahasiswa), count, fp);
    fclose(fp);

    printf("\n=== Data dari Binary File ===\n");
    for (int i = 0; i < count; i++) {
        printf("%d. %s (Umur: %d, IPK: %.2f)\n",
               i+1, hasil[i].nama, hasil[i].umur, hasil[i].ipk);
    }

    return 0;
}

10. Preprocessor dan Header

Preprocessor di C berjalan sebelum proses kompilasi. Semua direktif preprocessor diawali dengan #.

Directives Umum

C β€” Preprocessor
// ===== Include Guards (mencegah double inclusion) =====
// mathutils.h
#ifndef MATHUTILS_H
#define MATHUTILS_H

// Deklarasi fungsi
int tambah(int a, int b);
int kurang(int a, int b);

#endif // MATHUTILS_H

// ===== Macro =====
#define PI 3.14159265358979
#define MAX_SIZE 100
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))

// Conditional compilation
#ifdef DEBUG
    #define LOG(msg) printf("[DEBUG] %s\n", msg)
#else
    #define LOG(msg)  // Tidak melakukan apa-apa
#endif

// Stringification
#define STRINGIFY(x) #x
#define CONCAT(a, b) a##b

#include <stdio.h>

int main() {
    printf("PI = %f\n", PI);
    printf("5^2 = %d\n", SQUARE(5));
    printf("Max(10, 20) = %d\n", MAX(10, 20));

    LOG("Program dimulai");  // Hanya aktif jika -DDEBUG

    printf("STRINGIFY: %s\n", STRINGIFY(hello world));
    int xy = 100;
    printf("CONCAT: %d\n", CONCAT(x, y));  // xy β†’ 100

    // Predefined macros
    printf("File: %s\n", __FILE__);
    printf("Line: %d\n", __LINE__);
    printf("Date: %s\n", __DATE__);
    printf("Time: %s\n", __TIME__);

    return 0;
}

Dynamic Memory Allocation

C β€” Dynamic Memory
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    // malloc β€” alokasi memori tanpa inisialisasi
    int *arr = (int*)malloc(5 * sizeof(int));
    if (arr == NULL) {
        printf("Alokasi memori gagal!\n");
        return 1;
    }

    // Gunakan memori
    for (int i = 0; i < 5; i++) {
        arr[i] = (i + 1) * 10;
    }

    printf("Array: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // calloc β€” alokasi dengan inisialisasi 0
    int *zeros = (int*)calloc(5, sizeof(int));
    printf("Calloc[0] = %d\n", zeros[0]);  // 0

    // realloc β€” ubah ukuran memori
    arr = (int*)realloc(arr, 10 * sizeof(int));
    for (int i = 5; i < 10; i++) {
        arr[i] = (i + 1) * 10;
    }

    printf("Array setelah realloc: ");
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // free β€” bebaskan memori!
    free(arr);
    free(zeros);
    arr = NULL;   // Good practice
    zeros = NULL;

    // Linked list sederhana menggunakan dynamic memory
    typedef struct Node {
        int data;
        struct Node *next;
    } Node;

    Node *head = NULL;
    for (int i = 5; i >= 1; i--) {
        Node *new_node = (Node*)malloc(sizeof(Node));
        new_node->data = i * 10;
        new_node->next = head;
        head = new_node;
    }

    printf("\nLinked List: ");
    Node *current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");

    // Bebaskan linked list
    current = head;
    while (current != NULL) {
        Node *temp = current;
        current = current->next;
        free(temp);
    }

    return 0;
}

11. Best Practices

Berikut beberapa best practices saat menulis program C untuk menghindari bug dan masalah keamanan.

Praktik Penjelasan
Inisialisasi variabelSelalu inisialisasi variabel saat deklarasi untuk menghindari garbage value
Check NULL pointerSelalu cek hasil malloc/calloc/fopen apakah NULL
Free memorySelalu free() memori yang sudah dialokasikan setelah selesai
Avoid gets()Gunakan fgets() karena gets() rentan buffer overflow
Bounds checkingSelalu cek indeks array agar tidak out-of-bounds
Const correctnessGunakan const untuk pointer/variabel yang tidak berubah
Compiler warningsKompilasi dengan -Wall -Wextra untuk menangkap potensi bug
Include guardsSelalu gunakan #ifndef/#define/#endif di header file
C β€” Safe Coding
// Kompilasi dengan warning flags:
// gcc -Wall -Wextra -Werror -std=c11 -o program program.c

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

// Gunakan const untuk parameter input
void cetak(const char *pesan) {
    printf("%s\n", pesan);
}

// Selalu cek return value
int baca_angka(const char *prompt) {
    char buffer[32];
    printf("%s", prompt);
    if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
        return -1;
    }
    return atoi(buffer);
}

// Safe string copy
void safe_strcpy(char *dest, const char *src, size_t dest_size) {
    strncpy(dest, src, dest_size - 1);
    dest[dest_size - 1] = '\0';
}

int main() {
    // Contoh safe coding
    int *data = (int*)malloc(100 * sizeof(int));
    if (data == NULL) {
        fprintf(stderr, "Gagal alokasi memori!\n");
        return EXIT_FAILURE;
    }

    // ... gunakan data ...

    free(data);
    data = NULL;  // Hindari dangling pointer

    cetak("Program selesai dengan aman!");
    return EXIT_SUCCESS;
}

12. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang C Programming:

Pertanyaan 1: Apa fungsi dari operator & dalam deklarasi int *ptr = &x;?

a) Mengalikan nilai x dengan pointer
b) Mendapatkan alamat memori dari variabel x
c) Mengubah tipe data x menjadi pointer
d) Menghapus variabel x dari memori

Pertanyaan 2: Apa output dari kode berikut?
int arr[] = {10, 20, 30}; printf("%d", *(arr + 1));

a) 10
b) 20
c) 30
d) Error

Pertanyaan 3: Apa perbedaan utama antara malloc() dan calloc()?

a) malloc lebih cepat, calloc lebih lambat
b) calloc menginisialisasi memori ke 0, malloc tidak
c) malloc untuk tipe primitif, calloc untuk struct
d) Tidak ada perbedaan

Pertanyaan 4: Mengapa gets() tidak direkomendasikan di C?

a) Terlalu lambat dibanding fgets()
b) Tidak bisa membaca string
c) Tidak memiliki batasan buffer, rentan buffer overflow
d) Hanya tersedia di Linux

Pertanyaan 5: Apa yang terjadi jika kita tidak memanggil free() setelah malloc()?

a) Program akan error saat kompilasi
b) Memory leak β€” memori yang dialokasikan tidak bisa digunakan lagi
c) Memori otomatis dibebaskan saat program selesai
d) B dan C benar
πŸ” Zoom
100%
🎨 Tema