typedef

Memberi nama tipe yang lebih bersih dan peran typedef dalam menulis kode portabel.

Daftar isi

Kata kunci struct yang menyertai setiap deklarasi variabel membuat kode panjang dan berulang. typedef membuat alias untuk sebuah tipe, yaitu nama lain yang dipakai sebagaimana tipe asalnya, sehingga tipe yang sama dapat ditulis dengan satu kata saja. Topik ini membahas pembuatan alias untuk struct dan tipe dasar, aturan typedef pada struct yang merujuk dirinya sendiri, serta perannya dalam menulis kode yang mudah disesuaikan antarplatform.

Membuat alias tipe#

Pernyataan typedef ditulis seperti deklarasi variabel biasa, kemudian nama variabelnya menjadi nama tipe. Setelah pernyataan itu, alias dipakai sebagaimana tipe bawaan, baik untuk mendeklarasikan variabel, parameter, maupun nilai kembali. Alias bukan tipe baru, melainkan nama lain dari tipe yang sama, sehingga keduanya dapat saling ditukar tanpa konversi apa pun.

c alias-titik.c
#include <stdio.h>

typedef struct {
    int x;
    int y;
} Titik;

void cetak(Titik t) {
    printf("(%d, %d)\n", t.x, t.y);
}

int main(void) {
    Titik a = {3, 4};
    Titik b = {6, 8};

    cetak(a);
    cetak(b);

    return 0;
}
text Keluaran
(3, 4)
(6, 8)

Definisi typedef struct { ... } Titik; membuat struct tanpa tag sekaligus memberinya nama Titik. Deklarasi variabel cukup ditulis Titik a; tanpa kata kunci struct, dan parameter fungsi cetak ikut menjadi ringkas. Dengan satu kata tambahan pada definisinya, seluruh pemakaian tipe tersebut setelahnya menjadi lebih pendek dan lebih mudah dibaca.

Alias juga berlaku untuk tipe dasar, dan bentuk inilah yang paling sering dijumpai pada kode nyata.

c Alias untuk tipe dasar
// tidak-dijalankan
typedef unsigned int Meter;
typedef unsigned long long Hitungan;

Setelah dua alias di atas dideklarasikan, pernyataan Meter tinggi = 150; lebih bermakna daripada unsigned int tinggi = 150; karena satuan pengukurannya terbaca dari tipenya. Kompilator tetap memperlakukan Meter sebagai unsigned int biasa, sehingga operasi aritmetika dan perbandingannya tidak berubah sama sekali. Manfaatnya murni pada keterbacaan dan dokumentasi, tetapi manfaat itu terasa besar pada program yang panjang karena maksud setiap variabel terbaca dari tipenya.

Struct bertag dan tipe yang merujuk dirinya sendiri#

Struct yang memiliki anggota berupa pointer ke struct sejenis wajib memakai tag. Penulisan struct Simpul * di dalam tubuh definisi memerlukan tag karena nama aliasnya belum ada pada saat baris itu dibaca kompiler. Bentuk yang lazim menyatukan keduanya, yaitu tag dipakai untuk rujukan internal dan alias dipakai untuk seluruh pemakaian sesudahnya.

c simpul-berantai.c
#include <stdio.h>
#include <stddef.h>

typedef struct Simpul {
    int nilai;
    struct Simpul *berikut;
} Simpul;

int main(void) {
    Simpul kedua   = {30, NULL};
    Simpul pertama = {10, &kedua};

    Simpul *penunjuk = &pertama;
    while (penunjuk != NULL) {
        printf("%d\n", penunjuk->nilai);
        penunjuk = penunjuk->berikut;
    }

    return 0;
}
text Keluaran
10
30

Definisi typedef struct Simpul { ... } Simpul; menetapkan tag sekaligus alias dengan nama yang sama. Anggota berikut bertipe struct Simpul * merujuk tag yang sedang didefinisikan, sehingga satu simpul dapat menunjuk simpul lain. Program menautkan dua simpul secara statis, lalu menelusurinya dengan pointer penunjuk sampai anggota berikut bernilai NULL. Pola tautan semacam ini menjadi dasar struktur data berantai seperti linked list.

Alias tidak terbatas pada struct dan pointer. Array pun boleh diberi alias, misalnya typedef int Matriks[3][3]; yang membuat Matriks papan; setara dengan int papan[3][3];. Bentuk ini menjaga setiap deklarasi matriks pada satu program tetap konsisten, dan perubahan ordonya cukup dilakukan pada satu baris aliasnya.

typedef untuk kode portabel#

Ukuran tipe dasar C dapat berbeda antarplatform, sedangkan alias memisahkan pemakaian tipe dari pemilihannya. Satu baris typedef double Suhu; menetapkan tipe untuk seluruh program, dan perubahan ke float cukup dilakukan pada baris itu saja. Pustaka standar menerapkan pola yang sama, misalnya uint32_t pada header stdint.h yang menjamin lebar 32 bit di semua platform. Tipe size_t yang menjadi tipe kembali sizeof juga merupakan typedef pustaka standar, yaitu tipe bilangan bulat tak bertanda yang cukup untuk menampung ukuran objek apa pun.

c portabel.c
#include <stdio.h>

typedef double Suhu;

Suhu ke_fahrenheit(Suhu celsius) {
    return celsius * 9.0 / 5.0 + 32.0;
}

int main(void) {
    Suhu pagi  = 24.5;
    Suhu siang = 31.0;

    printf("Pagi  : %.1f C = %.1f F\n", pagi, ke_fahrenheit(pagi));
    printf("Siang : %.1f C = %.1f F\n", siang, ke_fahrenheit(siang));

    return 0;
}
text Keluaran
Pagi  : 24.5 C = 76.1 F
Siang : 31.0 C = 87.8 F

Seluruh pernyataan pada program di atas menyebut Suhu dan tidak ada satu pun yang bergantung pada tipe aslinya. Mengubah ketelitian perhitungan ke float atau long double cukup dengan menyunting satu baris typedef. Kemudahan penyesuaian inilah yang membuat typedef sering muncul pada kode yang menuntut portabilitas, bersama header stdint.h untuk lebar tipe yang pasti.

Peran lain yang menonjol adalah menyederhanakan deklarasi pointer fungsi yang sintaksnya panjang, sebagaimana banyak dijumpai pada pustaka berbasis callback. Tanpa alias, tanda * dan daftar parameter harus ditulis ulang pada setiap deklarasi, sedangkan alias merangkumnya menjadi satu nama.

c Alias untuk tipe pointer fungsi
// tidak-dijalankan
typedef int (*Operasi)(int, int);

Operasi hitung = &tambah;   /* deklarasi menjadi satu kata */

Kesalahan umum#

Alias yang menyembunyikan pointer sering menjadi sumber kekeliruan pembacaan. Pernyataan typedef char* Teks; membuat deklarasi Teks a, b; menghasilkan dua pointer sekaligus, sedangkan pembaca cenderung menduga b berupa char biasa karena tanda * tidak tampak pada baris deklarasinya. Menyertakan tanda * di dalam alias diperbolehkan, tetapi menuliskannya pada setiap deklarasi variabel membuat maksudnya lebih mudah dibaca.

Kekeliruan kedua adalah menganggap alias sebagai tipe baru yang ketat. Karena alias hanyalah nama lain, variabel bertipe alias dan variabel dengan deklarasi struct yang sama saling ditugaskan tanpa konversi. Kompiler pun tidak memberikan peringatan bila keduanya tercampur dalam satu program.

Kekeliruan ketiga berkaitan dengan letak pernyataannya. Alias mengikuti aturan lingkup sebagaimana deklarasi lain, sehingga typedef yang ditulis di dalam fungsi hanya dikenal di dalam fungsi itu. Alias yang dibutuhkan lebih dari satu fungsi dideklarasikan di tingkat berkas, umumnya di berkas header, agar seluruh kode yang menyertakannya memakai nama yang sama.

Ringkasan#

  • typedef memberi alias bagi sebuah tipe sehingga deklarasi variabel, parameter, dan nilai kembali menjadi ringkas.
  • Alias bukan tipe baru, melainkan nama lain yang saling menukar dengan tipe asalnya tanpa konversi.
  • Struct yang merujuk dirinya sendiri memerlukan tag, dan bentuk lazimnya menyandingkan tag dengan alias yang bernama sama.
  • Satu baris typedef memisahkan pemilihan tipe dari pemakaiannya, pola yang diterapkan pustaka standar pada uint32_t.

Referensi#