Nilai yang ditulis langsung di dalam kode maupun nilai yang diberi nama keduanya disebut konstanta, karena sama-sama tidak boleh berubah selama program berjalan. Topik ini membahas dua cara C menamai konstanta, yaitu kata kunci const dan arahan #define, lalu membahas bentuk-bentuk literal (literal), yaitu nilai yang dituliskan apa adanya di dalam kode seperti 42, 3.14, dan "teks". Setelah membacanya, angka-angka misterius di dalam kode dapat diganti nama yang bermakna dan bentuk setiap literal dapat dikenali.
Konstanta bernama dengan const#
Kata kunci const diletakkan di depan deklarasi variabel untuk melarang isi variabel itu diganti setelah diinisialisasi. Segala upaya penugasan ulang akan ditolak kompiler, sehingga kesalahan logika tertangkap pada saat kompilasi, bukan saat program berjalan. Program berikut memakai const untuk menyimpan tarif pajak dan #define untuk menyimpan laju kirim data:
#include <stdio.h>
#define LAJU_KIRIM 2400
int main(void) {
const double PAJAK = 0.11;
double harga = 250000.0;
double total = harga + harga * PAJAK;
printf("Total dengan pajak: %.2f\n", total);
printf("Laju kirim data : %d byte per detik\n", LAJU_KIRIM);
return 0;
}Total dengan pajak: 277500.00
Laju kirim data : 2400 byte per detikAngka 0.11 dan 2400 yang sebelumnya hanya berupa angka kini memiliki nama PAJAK dan LAJU_KIRIM, sehingga maksudnya terbaca langsung dari kode. Konstanta semacam ini lazim ditulis dengan huruf kapital dan garis bawah sebagai pemisah agar mudah dibedakan dari variabel biasa. Selain memperjelas maksud, pemberian nama juga memusatkan titik perubahan, karena menaikkan tarif cukup dilakukan pada satu baris saja. Percobaan mengubah isi const ditolak kompiler:
// tidak-dijalankan
const double PAJAK = 0.11;
PAJAK = 0.15;Apabila baris PAJAK = 0.15; disertakan dalam program, pesan errornya berbunyi:
salah-const.c: In function ‘main’:
salah-const.c:5:11: error: assignment of read-only variable ‘PAJAK’
5 | PAJAK = 0.15;
| ^Frasa read-only variable menyatakan inti perannya, yaitu variabel itu hanya boleh dibaca. Karena pemeriksaannya dilakukan kompiler dan tipenya tetap diketahui, const adalah pilihan utama untuk konstanta di dalam kode C modern.
Makro #define dari preprosesor#
Arahan #define LAJU_KIRIM 2400 bekerja dengan cara yang berbeda. Arahan ini diproses oleh preprosesor, tahap yang sudah diperkenalkan pada topik Alur Kompilasi. Cara kerjanya adalah mengganti setiap kemunculan teks LAJU_KIRIM dengan teks 2400 sebelum kompilasi dimulai. Penggantian teks semacam ini disebut makro (macro) tanpa argumen. Karena dilakukan sebelum kompiler bekerja, makro tidak memiliki tipe maupun lokasi memori.
Perbedaan cara kerja itu menimbulkan perbedaan praktis yang dirangkum tabel berikut.
| Aspek | const | #define |
|---|---|---|
| Yang diperiksa | kompiler, lengkap dengan tipe | preprosesor, hanya teks |
| Tipe data | ada, misalnya double | tidak ada |
| Cakupan nama | mengikuti aturan lingkup | berlaku dari baris define ke bawah |
| Muncul pada debugger | ya, sebagai nama | tidak, sudah diganti angka |
| Pesan error | menunjuk nama konstanta | menunjuk hasil penggantian |
Tabel tersebut menjelaskan mengapa const diutamakan untuk nilai bertipe. Makro #define tetap dipakai luas untuk nilai yang bentuknya bukan ekspresi tunggal dan untuk pemilihan fitur saat kompilasi. Karena itulah makro dibahas lebih dalam pada modul Preprosesor.
Literal bilangan bulat dan pecahan#
Literal bilangan bulat ditulis dalam bentuk desimal secara bawaan, tetapi C juga menerima bentuk oktal berawalan 0 dan heksadesimal berawalan 0x. Ketiga bentuk itu menyatakan nilai yang sama, sebagaimana dibandingkan baris pertama program berikut. Akhiran (suffix) L memaksa literal berukuran long, sedangkan akhiran f pada literal pecahan memaksa tipe float:
#include <stdio.h>
int main(void) {
printf("%d %d %d\n", 42, 052, 0x2A);
printf("%ld\n", 3000000000L);
printf("%f\n", 1e3);
printf("%c %c\n", 'A', 65);
printf("Nama\tNilai\n");
printf("Kutipan: \"dicetak\", backslash: \\\n");
return 0;
}42 42 42
3000000000
1000.000000
A A
Nama Nilai
Kutipan: "dicetak", backslash: \Baris pertama membuktikan 42, 052, dan 0x2A bernilai sama, yaitu empat puluh dua, dalam tiga sistem penulisan yang berbeda. Bentuk heksadesimal banyak dipakai saat bekerja dengan bit dan alamat memori karena setiap dua digitnya tepat mewakili satu byte. Baris kedua menunjukkan alasan akhiran L: angka 3000000000 melampaui rentang int, sehingga tanpa akhiran L kompiler akan memperingatkan nilai literal yang terlalu besar.
Literal pecahan dapat ditulis dalam bentuk notasi ilmiah, dan 1e3 pada baris ketiga berarti satu kali sepuluh pangkat tiga, yaitu 1000. Tanpa akhiran apa pun, literal pecahan bertipe double, sedangkan 1.5f bertipe float. Ketelitian keduanya sudah dibahas pada topik Variabel dan Tipe Data.
Literal char, string, dan escape sequence#
Literal char ditulis di antara tanda kutip tunggal, misalnya 'A', dan nilainya adalah kode angka karakter tersebut. Baris keempat program di atas membandingkan 'A' dengan angka 65, dan keduanya dicetak sebagai huruf A oleh %c. Persamaan hasil itu membuktikan 'A' dan 65 bernilai sama. Literal string ditulis di antara tanda kutip ganda, misalnya "Nama", dan merupakan deretan karakter yang akan dibahas lebih rinci pada modul Array dan String.
Di dalam literal char dan string, beberapa karakter tidak dapat diketik langsung, misalnya pindah baris dan tanda kutip itu sendiri. Karakter semacam ini ditulis memakai escape sequence, yaitu tanda garis miring terbalik diikuti satu karakter atau kode yang mewakilinya. Tabel berikut merangkum yang paling sering dipakai.
| Escape sequence | Arti |
|---|---|
\n | pindah baris |
\t | tab horizontal |
\\ | tanda garis miring terbalik |
\" | tanda kutip ganda di dalam string |
\' | tanda kutip tunggal di dalam char |
\0 | karakter nol penanda akhir string |
Baris kelima dan keenam program literal.c memperlihatkan \t yang mencetak tab sehingga kolomnya sejajar, \" yang mencetak kutip ganda di dalam teks, dan \\ yang mencetak satu garis miring terbalik. Tanpa penulisan khusus ini, tanda kutip di tengah string akan dianggap penutup string dan kompilasi gagal.
Kesalahan umum#
Kesalahan yang khas pada makro adalah menaruh titik koma di akhir #define. Karena preprosesor hanya mengganti teks, titik koma itu ikut tersisip ke setiap tempat nama makro dipakai, lalu memicu error pada baris pemakaiannya, bukan pada baris definisinya:
// tidak-dijalankan
#define PI 3.14;
int main(void) {
printf("%f\n", PI);
return 0;
}salah-define.c: In function ‘main’:
salah-define.c:3:16: error: expected ‘)’ before ‘;’ token
3 | #define PI 3.14;
| ^
salah-define.c:6:20: note: in expansion of macro ‘PI’
6 | printf("%f\n", PI);
| ^~Pesan in expansion of macro 'PI' penting diperhatikan karena error muncul pada hasil pengembangan makro, sehingga baris yang ditunjuk pertama kali tidak selalu baris yang salah. Kesalahan kedua yang mirip adalah menulis #define dengan tanda = seperti penugasan, misalnya #define PI = 3.14, karena hasil penggantiannya menjadi = 3.14 dan tidak dapat dipakai dalam perhitungan. Arahan #define cukup ditulis #define PI 3.14 tanpa tanda = maupun titik koma.
Kesalahan ketiga terjadi pada literal oktal. Awalan 0 membuat angka dibaca sebagai oktal, sehingga penulisan 052 yang dimaksudkan sebagai lima puluh dua justru bernilai empat puluh dua. Angka tanggal, nomor telepon, atau kode lain yang sengaja ditulis dengan nol di depan bisa berubah nilai tanpa terasa, sehingga nol di depan hanya ditulis bila bentuk oktal memang dikehendaki.
Ringkasan#
constmembuat variabel yang tidak dapat ditugaskan ulang, lengkap dengan tipe dan pemeriksaan kompiler, sehingga menjadi pilihan utama konstanta bertipe.#definebekerja pada preprosesor dengan mengganti teks, tidak memiliki tipe, dan tanpa titik koma maupun tanda=.- Literal bilangan bulat dapat ditulis desimal, oktal berawalan
0, dan heksadesimal berawalan0x, dengan akhiranLdanUmengatur ukurannya. - Literal pecahan bertipe
doublesecara bawaan, ataufloatbila diberi akhiranf, dan dapat ditulis notasi ilmiah seperti1e3. - Escape sequence seperti
\n,\t,\\, dan\"menuliskan karakter yang tidak bisa diketik langsung di dalam literal.
Referensi#
- C keywords: const — cppreference
— Perilaku kualifikasi
constpada deklarasi C. - Integer constant — cppreference — Bentuk literal bilangan bulat beserta awalan sistem bilangan dan akhiran ukurannya.
- Escape sequence — cppreference — Daftar lengkap escape sequence pada C beserta makna setiap notasi.