Setiap kali kita mendeklarasikan variabel struct, kata kunci struct wajib ditulis ulang: struct Mahasiswa mhs;, struct Buku daftar[10];. Pada program besar, pengulangan kata struct ribuan kali terasa berisik dan membebani pembacaan. C menyediakan typedef untuk membuat alias tipe baru, sehingga Mahasiswa_t bisa langsung dipakai tanpa awalan struct. Pada chapter ini kita akan membandingkan penulisan dengan dan tanpa typedef, memahami tiga pola umum yang dipakai di industri, dan melihat bagaimana typedef juga bekerja pada enum dan union.
Apa Itu typedef #
typedef adalah kata kunci C yang membuat nama alias untuk tipe yang sudah ada. Bentuk umumnya: typedef <tipe_asli> <nama_alias>;. Setelah itu, <nama_alias> bisa dipakai seperti tipe bawaan—tanpa perlu menulis struct, enum, atau union lagi. typedef tidak membuat tipe baru; Mahasiswa_t dan struct Mahasiswa (jika keduanya mengacu ke definisi yang sama) adalah tipe yang sama dengan nama berbeda.
Mekanisme kerja typedef di balik layar: compiler menyimpan pemetaan nama alias ke tipe asli. Ketika compiler melihat Mahasiswa_t, compiler mencari pemetaan dan menggantinya dengan tipe asli yang dimaksud sebelum melakukan type-checking. Karena itu, semua operasi yang berlaku pada tipe asli juga berlaku pada alias.
Tiga Pola typedef pada struct #
Ada tiga pola yang sering muncul di kode nyata. Pertama, tanpa typedef—kita harus selalu menulis struct Mahasiswa. Kedua, anonymous struct + typedef—definisi struct tidak punya tag, dan typedef langsung membuat alias. Ketiga, tag + typedef—kita memberi tag sekaligus alias, sehingga keduanya bisa dipakai.
#include <stdio.h>
#include <string.h>
/* Tanpa typedef: harus menulis "struct Mahasiswa" */
struct Mahasiswa {
char nama[50];
int umur;
};
/* Dengan typedef: alias tipe "Mahasiswa_t" */
typedef struct {
char nama[50];
int umur;
float ipk;
} Mahasiswa_t;
/* Pola umum: tag + typedef agar keduanya bisa dipakai */
typedef struct Dosen {
char nama[50];
int nidn;
} Dosen;
int main(void) {
struct Mahasiswa m1;
strcpy(m1.nama, "Budi");
m1.umur = 21;
Mahasiswa_t m2 = {"Siti", 22, 3.85f};
Dosen d1 = {"Dr. Andi", 12345};
printf("m1: %s, %d tahun\n", m1.nama, m1.umur);
printf("m2: %s, %d tahun, IPK %.2f\n", m2.nama, m2.umur, m2.ipk);
printf("d1: %s, NIDN %d\n", d1.nama, d1.nidn);
/* Bandingkan ukuran tipe */
printf("sizeof(struct Mahasiswa) = %zu\n", sizeof(struct Mahasiswa));
printf("sizeof(Mahasiswa_t) = %zu\n", sizeof(Mahasiswa_t));
printf("sizeof(Dosen) = %zu\n", sizeof(Dosen));
return 0;
}Output yang Dihasilkan:
m1: Budi, 21 tahun
m2: Siti, 22 tahun, IPK 3.85
d1: Dr. Andi, NIDN 12345
sizeof(struct Mahasiswa) = 56
sizeof(Mahasiswa_t) = 60
sizeof(Dosen) = 56Mari kita telaah baris-baris kode di atas:
- Baris 6-9 (
struct Mahasiswa { ... };): pendefinisian tipe dengan tagMahasiswa, tanpatypedef. Untuk memakainya kita harus menulisstruct Mahasiswa(lihat baris 22). Ini adalah cara klasik yang paling eksplisit. - Baris 12-16 (
typedef struct { ... } Mahasiswa_t;): anonymous struct (tanpa tag) yang langsung diberi aliasMahasiswa_tmelaluitypedef. Karena tidak ada tag, kita tidak bisa menulisstruct Mahasiswa_t—itu akan jadi compile error. Yang benar adalah langsungMahasiswa_t(lihat baris 26). - Baris 19-22 (
typedef struct Dosen { ... } Dosen;): pendefinisian tipe dengan tagDosensekaligus aliasDosen. Sejak baris ini, baikstruct DosenmaupunDosenmerujuk ke tipe yang sama. Pola ini populer di pustaka standar C (misalnya di<stdio.h>untuk tipeFILE). - Baris 30-32 (
sizeof(...)): tiga pemanggilansizeofmenunjukkan ukuran masing-masing tipe.struct Mahasiswa(50 + 4 + padding = 56) berbeda dariMahasiswa_t(50 + 4 + 4 + padding = 60) karena keduanya memang struct berbeda dengan member berbeda.Dosen(50 + 4 + padding = 56) sama denganstruct Dosenkarena keduanya merujuk ke definisi yang sama.
typedef Berlaku untuk enum dan union Juga #
typedef tidak terbatas pada struct. Kita bisa memakai pola yang sama untuk enum dan union. Hal ini membuat deklarasi variabel konstanta terhitung dan data union lebih ringkas.
#include <stdio.h>
/* typedef pada struct primitif yang sering dipakai */
typedef struct {
int x;
int y;
} Point;
typedef struct {
Point start;
Point end;
} LineSegment;
/* typedef juga bekerja pada enum dan union */
typedef enum { MERAH, HIJAU, BIRU } Warna;
/* Fungsi yang memakai alias */
void tampilkan_titik(Point p) {
printf("(%d, %d)", p.x, p.y);
}
int main(void) {
LineSegment garis = {{0, 0}, {5, 5}};
Warna c = HIJAU;
printf("Garis dari ");
tampilkan_titik(garis.start);
printf(" ke ");
tampilkan_titik(garis.end);
printf("\nWarna indeks: %d\n", c);
return 0;
}Output yang Dihasilkan:
Garis dari (0, 0) ke (5, 5)
Warna indeks: 1Pada contoh di atas, Point adalah alias untuk anonymous struct berisi dua int. LineSegment punya dua member bertipe Point—disebut nested struct, yang akan kita bahas lebih lanjut di chapter tersendiri. Warna adalah alias untuk enum dengan tiga konstanta: MERAH = 0, HIJAU = 1, BIRU = 2. Karena c = HIJAU, indeks yang tercetak adalah 1.