Cara Menggunakan Struct dalam Bahasa C

Laptop menampilkan kode bahasa C dengan definisi struct di meja kayu

Struct adalah cara membuat tipe data buatan sendiri yang bisa menampung beberapa nilai dengan tipe berbeda sekaligus. Kalau kamu biasanya memakai array untuk menyimpan banyak angka, struct memberi fleksibilitas lebih karena tiap anggota boleh punya tipe yang berbeda. Panduan ini membahas cara menggunakan struct dalam bahasa C mulai dari deklarasi sampai dipakai di fungsi.

Apa Itu Struct dan Kenapa Dipakai

Bayangkan kamu ingin menyimpan data seorang mahasiswa: nama, umur, dan nilai akhir. Kalau pakai variabel terpisah, kamu perlu tiga variabel untuk satu orang. Kalau ada sepuluh mahasiswa, jumlah variabel membengkak jadi tiga puluh.

Struct menyelesaikan masalah itu. Kamu mendefinisikan satu bentuk data yang menampung ketiga field, lalu membuat variabel sebanyak yang dibutuhkan. Setiap variabel punya isi lengkap untuk satu entitas.

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

Setelah didefinisikan, struct Mahasiswa bisa dipakai seperti tipe data bawaan. Kamu bisa membuat variabel, mengirimnya ke fungsi, atau menyimpannya di array.

Cara Mendeklarasikan dan Mengisi Struct

Ada beberapa cara membuat variabel dari struct. Yang paling umum, deklarasikan dulu tipenya, lalu buat variabel terpisah.

struct Mahasiswa mhs1;
strcpy(mhs1.nama, "Andi");
mhs1.umur = 20;
mhs1.nilai = 85.5;

Tanda titik dipakai untuk mengakses anggota struct. Urutan pengisian tidak harus sama dengan urutan deklarasi field.

Cara lain adalah menginisialisasi langsung saat dideklarasikan:

struct Mahasiswa mhs2 = {"Budi", 21, 78.0};

Di sini urutannya harus sesuai: nama, umur, baru nilai. Kalau kebalik, compiler tidak akan protes karena tipenya berbeda, tapi isinya jadi kacau.

Memakai typedef untuk Nama yang Lebih Pendek

Menulis struct Mahasiswa berulang kali terasa melelahkan. Kamu bisa memberi alias dengan typedef supaya cukup menulis Mahasiswa saja.

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

Setelah itu, deklarasinya jadi lebih ringkas: Mahasiswa mhs3;. Cara ini sering dipakai di kode produksi karena lebih enak dibaca.

Mengakses Anggota Struct lewat Pointer

Kalau kamu punya pointer ke struct, ada operator khusus bernama tanda panah (->). Operator ini setara dengan mendereferensi pointer lalu mengakses anggotanya.

Mahasiswa mhs = {"Citra", 22, 90.0};
Mahasiswa *ptr = &mhs;

printf("%sn", ptr->nama);
printf("%dn", ptr->umur);

Dua baris berikut artinya sama persis, tapi yang kedua lebih sering dipakai.

(*ptr).nama
ptr->nama

Konsep pointer di sini penting karena banyak fungsi pustaka dan fungsi buatan sendiri menerima struct dalam bentuk pointer. Kalau kamu belum nyaman dengan konsep alamat memori, ada baiknya membaca cara menggunakan pointer pada bahasa C terlebih dahulu supaya tidak bingung saat melihat tanda bintang dan tanda panah bercampur.

Struct di Dalam Array

Menyimpan banyak data dengan tipe yang seragam paling praktis pakai array of struct. Setiap elemen array berisi satu struct utuh.

Mahasiswa kelas[3] = {
    {"Andi", 20, 85.5},
    {"Budi", 21, 78.0},
    {"Citra", 22, 90.0}
};

for (int i = 0; i < 3; i++) {
    printf("%s - %d - %.1fn",
           kelas[i].nama,
           kelas[i].umur,
           kelas[i].nilai);
}

Setelah tersimpan dalam array, kamu bisa mengurutkan, mencari, atau menghitung rata-rata dengan loop biasa. Ini pola yang sering muncul saat mengerjakan tugas kuliah atau proyek kecil.

Mengirim Struct ke Fungsi

Struct bisa diteruskan ke fungsi dengan dua cara: lewat nilai atau lewat pointer. Keduanya punya konsekuensi berbeda.

Lewat Nilai

Kalau kamu kirim struct langsung, C akan menyalin seluruh isinya. Untuk struct kecil, cara ini aman dan simpel. Tapi kalau structnya besar, penyalinan memakan waktu dan memori tambahan.

void cetak(Mahasiswa m) {
    printf("%s, %d tahun, nilai %.1fn", m.nama, m.umur, m.nilai);
}

Perubahan di dalam fungsi tidak memengaruhi struct asli, karena yang diubah adalah salinan.

Lewat Pointer

Kalau fungsi perlu mengubah isi struct, kirim alamatnya. Dengan begitu, fungsi bekerja langsung pada data asli.

void naikkanNilai(Mahasiswa *m, float tambahan) {
    m->nilai += tambahan;
}

// Pemanggilan
naikkanNilai(&mhs, 5.0);

Cara ini juga lebih hemat karena hanya alamat yang disalin, bukan seluruh isi struct. Untuk struct yang punya banyak field, ini pilihan yang lebih masuk akal.

Struct Bersarang

Field di dalam struct boleh berupa struct lain. Misalnya, alamat lengkap bisa dipecah jadi beberapa field dan dibungkus dalam struct sendiri.

typedef struct {
    char jalan[50];
    char kota[30];
} Alamat;

typedef struct {
    char nama[50];
    Alamat alamat;
} Pelanggan;

Untuk mengaksesnya, tinggal runtutkan tanda titiknya: pelanggan.alamat.kota. Struktur bersarang seperti ini membuat kode lebih rapi dibanding menyebar semua field dalam satu struct besar.

Hal yang Sering Bikin Pemula Tersandung

  • Lupa tanda titik koma setelah kurung kurawal penutup deklarasi struct. Compiler akan mengeluh di baris berikutnya, bukan di baris struct itu sendiri.
  • Menggunakan = untuk menyalin string ke field char[]. Pakai strcpy atau snprintf.
  • Membandingkan dua struct dengan ==. Operator itu tidak bekerja untuk struct secara keseluruhan, kamu harus membandingkan per field.
  • Mendeklarasikan struct di dalam fungsi lalu memakainya di fungsi lain. Deklarasikan di luar fungsi supaya bisa diakses di mana saja.

Kesalahan-kesalahan ini muncul karena struct terlihat mirip dengan konsep kelas di bahasa lain, padahal cara kerjanya berbeda. Bahasa C tidak punya method atau pewarisan di dalam struct, jadi semua operasi ditulis sebagai fungsi terpisah.

Ringkasan

Struct membantumu mengelompokkan data yang saling berkaitan dalam satu wadah. Definisikan tipenya, isi anggotanya lewat tanda titik, dan gunakan tanda panah saat bekerja dengan pointer. Untuk fungsi yang perlu mengubah isi, kirim struct lewat pointer supaya perubahan terasa di luar fungsi. Mulailah dari struct sederhana, lalu tambahkan nesting kalau memang perlu.

Pertanyaan yang Sering Diajukan

Apa bedanya struct dan union di bahasa C?

Struct menyimpan semua anggotanya secara terpisah, jadi memori yang dipakai adalah total dari semua field. Union hanya menyediakan satu ruang memori yang dipakai bergantian oleh anggotanya. Pada union, mengisi satu field akan menimpa nilai field lain.

Bisakah struct berisi array dengan ukuran yang diisi pengguna?

Tidak langsung. Ukuran array di dalam struct harus diketahui saat kompilasi. Kalau butuh panjang dinamis, pakai pointer ke memori yang dialokasikan dengan malloc, lalu simpan panjangnya di field terpisah.

Apakah struct bisa dibandingkan langsung dengan operator ==?

Tidak. Operator == tidak didefinisikan untuk tipe struct secara keseluruhan. Kamu perlu menulis fungsi pembanding sendiri yang memeriksa tiap field satu per satu, atau memakai memcmp kalau tidak ada padding yang mengganggu.