author Ahmad Muhardian

Belajar C #18: Memahami Preprocessor dan Macro


C Macro

Pada tutorial ini kita akan mempelajari tentang preprocessor dan macro di C.

Ini penting.

Supaya kamu bisa paham proses dibalik kode program C sebelum dilakukan compile.

Jadi apa itu preprocessor dan macro?

Gimana cara pakainya?

Mari kita pelajari!

Apa itu Preprocessor dan Macro?

Sebelum kode program di-compile menjadi binary, kode program diproses dulu oleh preprocessor.

Hasil proses dari preprocessor berupa kode program C yang siap untuk di-compile.

preprocessor pada c

Mengapa harus dilakukan preprocessor?

Agar kita tidak menulis kode secara manual.

Maksudnya gimana tu?

Gini..

Coba perhatikan kode program ini:

#include <stdio.h>

void main(){
  printf("Hello World!\n");
}

Pada program ini, terdapat sebuah macro:

#include <stdio.h>

Fungsi macro ini untuk ngasi tau preprocessor supaya memasukan semua kode yang ada di file stdio.h ke dalam kode program kita.

Sehingga kita bisa menggunakan fungsi printf() di dalamnya.

Jika tidak ada preprocessor, maka kita harus memasukannya secara manual. Bisa dengan copas semua isi kode pada stdio.h ke dalam kode program kita.

Mau seperti itu?

Jelas tidak, ini pekerjaan yang melelahkan.

Karena itulah, kita membutuhkan preprocessor.

Jadi..

Preprocessor adalah proses yang dilakukan sebelum program di-compile berdasarkan macro yang diberikan. Hasil preprocessor adalah kode program, bukan file binary. Kode program inilah yang nantinya akan di-compile oleh compier.

preprocessor pada c

Jika ingin melihat hasil preprocessor, kita bisa gunakan perintah cpp atau gcc -E.

Contoh:

cpp hello_world.c

atau:

gcc -E hello_world.c

Maka hasilnya:

hasil preprocessor

Pada hasil preprocessor ini, semua kode yang ada di stdio.h dimasukan ke dalam kode yang kita tulis.

Ini karena kita menggunakan macro #include <stdio.h>.

Jadi..

Macro adalah kode-kode untuk memberikan instruksi kepada preprocesor.

Contoh macro:

#include <stdio.h>

Macro ini untuk memberi perintah ke preprocessor:

“Hi preprocessor, masukan semua kode program yang ada di stdio.h ke dalam kode program ini”.

Selain macro #include ada juga macro-macro yang lainnya.

Macro DirectiveFungsi Macro
#defineMendefiniskan konstanta dan fungsi
#includeuntuk menambahkan kode ke dalam program
#undefuntuk menghapus macro yang sudah didefinisikan
#ifdefuntuk mengecek apakah macro sudah didefinisikan
#ifndefuntuk mengecek apakah macro belum didefinisikan
#ifuntuk membuat kondisi if
#elseuntuk membuat alternatif untuk if
#elifuntuk membuat kondisi else if
#endifuntuk mengakhiri blok kondisi if
#erroruntuk mencetak pesan error ke stderr
#pragmauntuk ngasi instruksi ke compiler.

Macro directive adalah simbol-simbol atau kata-kata yang dipakai untuk membuat atau mendefinisikan macro.

Pendefinisian macro dapat ditulis di mana saja, bisa di dalam fungsi main maupun di luar. Bisa di header file maupun souce file.

Biar semakin paham, mari kita bahas beserta contohnya.

Directive #define dan #undefine

Seperti yang dibahas pada tabel tadi..

..direktif #define dan #undefine berfungsi untuk mendefinisikan dan menghapus definisi macro.

Contoh:

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

Artinya:

Definisikan konstanta dengan nama SCREEN_WIDTH dengan nilai 800 dan SCREEN_HEIGH 600.

Jika sebuah macro sudah didefinisikan di file lain, kita bisa definisikan ulang dengan menghapus definisinya terlebih dahulu dengan #undef.

Contoh:

#undef  FILE_SIZE
#define FILE_SIZE 42

Selain mendefinisikan konstanta, direktif #define juga bisa kita pakai untuk mendefinisikan fungsi.

Contoh:

#define square(sisi) ((sisi) * (sisi))
#define MAX(x,y) ((x) > (y) ? (x) : (y))

Ada dua macro yang berbentuk fungsi yang kita buat, yakni: square() dan MAX().

Jika ingin menggunakan macro tersebut, maka kita bisa panggil seperti fungsi biasa.

Contoh:

#include <stdio.h>

// mendefinisikan macro
#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
  // menggunakan macro
  printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
  return 0;
}

Jika di-compile dan dijalankan, maka hasil outputnya:

Max between 20 and 10 is 20

Jadi direktif #define dan #undefine berfungsi untuk membuat dan menghapus macro.

Predefined Macro

Predefined macro adalah macro-macro yang sudah ada atau sudah didefinisikan di komputer kita. Kita tinggal pakai aja.

Contoh predefined macro:

  • __DATE__ berisi tanggal saat ini;
  • __TIME__ berisi waktu saat ini;
  • __FILE__ berisi nama file dari kode program;
  • __LINE__ berisi nomor baris program.
  • __STDC__ berisi 1 jika program di-compile dengan standar ANSI.

Contoh penggunaan:

Buatlah file program baru dengan nama predefined_macro.c dengan isi sebagai beriikut.

#include <stdio.h>

void main() {

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

}

Hasilnya:

File : predefined_macro.c
Date : May 16 2022
Time : 03:36:24
Line : 8
ANSI : 1

Direktif Kondisi

Kita bisa membuat kondisi dengan direktif macro, ada beberapa direktif yang disediakan untuk membuat kondisi:

  • #if untuk kondisi if;
  • #else untuk kondisi else;
  • #elif untuk kondisi else if;
  • #endif untuk mentutup atau mengakhiri if;
  • #ifdef untuk mengecek jika macro sudah didefinisikan;
  • #ifndef untuk mengecek jika macro belum didefinisikan.

Contoh pengguaan:

#include <stdio.h>

#ifndef DEBUG
#define DEBUG true
#endif

void main(){
  #if defined(DEBUG)
  printf("Debugging mode is on\n");
  #else
  printf("Debugging mode is off\n");
  #endif
}

Maka hasil preprocessor-nya:

void main(){
  printf("Debugging mode is on\n");
}

Jadi kita bisa memilih kode mana yang akan di proses berdasarkan kondisi tertentu.

Operator pada Macro

Macro punya 4 operator yang bisa dipakai:

1. Operator Sambungan

Operator sambung menggunakan simbol backslash (\), fungsinya untuk menyambung definisi macro jika lebih dari satu baris.

Contoh:

#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

2. Operator Stringize (#)

Operator stringize menggunakan simbol pagar (#), berfungsi untuk mengubah parameter pada macro menjadi teks string.

#include <stdio.h>

#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Petani, Kode);
   return 0;
}

Mungkin kamu akan bertanya..

Saat pakai macro seperti ini:

message_for(Petani, Kode);

mengapa programnya tidak error, di sana kan gak ada tanda petik?

Ingat:

Macro diproses oleh preprocessor, bukan compiler. Jadi saat di-compile programnya akan bisa jalan karena sebelumnya sudah dilakukan preprocessing.

Kita bisa cek hasil preprocessor dengan perintah cpp.

cpp kode_program.c

Maka hasilnya:

int main(void) {
   printf("Petani" " and " "Kode" ": We love you!\n");
   return 0;
}

3. Operator Token Pasting

Operator token pasting berfungsi untuk mengambil nama variabel atau parameter yang diberikan ke macro. Operator ini menggunakan simbol pagar ganda (##).

Contoh:

#include <stdio.h>

#define tokenpaster(n) printf ("%d", token_##n)

int main(void) {
   int petani_kode = 40;
   tokenpaster(petani_kode);
   return 0;
}

Maka hasil preprocessor-nya:

int main(void) {
   int petani_kode = 40;
   printf ("%d", token_petani_kode);
   return 0;
}

4. Operator defined()

Operator defined() berfungsi untuk mengecek kondisi suatu macro. Apakah macro tersebut sudah didefinisikan atau tidak. Ini sama seperti direktif #ifdef dan #ifndef.

Contoh:

#include <stdio.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   printf("Here is the message: %s\n", MESSAGE);  
   return 0;
}

Maka hasil preprocessornya:

int main(void) {
   printf("Here is the message: %s\n", "You wish!");
   return 0;
}

Parameter untuk Macro

Parameter adalah variabel khusus yang dipakai oleh macro untuk diproses. Biasanya kita butuhkan saat membuat macro berbentuk fungsi.

Contoh:

#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

void main(void) {
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));
   return 0;
}

Maka hasil preprocessor-nya:

void main(void) {
   printf("Max between 20 and 10 is %d\n", ((10) > (20) ? (10) : (20)));
   return 0;
}

Apa Selanjutnya?

Macro dan preprocessing adalah fitur yang membantu kita dalam membuat kode program C. Sehingga kita bisa membuat kode program yang lebih singkat dibandingkan harus menulis semua kode berulang-ulang.

Selanjutnya silahkan pelajari tentang header file pada C untuk membuat program modular dan bisa digunakan kembali dengan macro #include.

Jika masih bingung, silahkan tanyakan di komentar ya.

Selamat belajar. 🙌