Arduino adalah hibrida aneh, di mana beberapa fungsionalitas C ++ digunakan di dunia yang disematkan — biasanya lingkungan C. Memang, banyak kode Arduino sangat C seperti.
C secara tradisional digunakan #define
s untuk konstanta. Ada sejumlah alasan untuk ini:
- Anda tidak dapat mengatur ukuran array menggunakan
const int
. - Anda tidak dapat menggunakan
const int
sebagai label pernyataan kasus (meskipun ini berfungsi di beberapa kompiler) - Anda tidak dapat menginisialisasi
const
dengan yang lainconst
.
Anda dapat memeriksa pertanyaan ini di StackOverflow untuk alasan lebih lanjut.
Jadi, apa yang harus kita gunakan untuk Arduino? Saya cenderung ke arah sana #define
, tetapi saya melihat beberapa kode menggunakan const
dan beberapa menggunakan campuran.
programming
c++
coding-standards
Cybergibbons
sumber
sumber
#define
adalah pilihan yang jelas. Contoh saya dalam penamaan pin Analog - seperti A5. Tidak ada tipe yang sesuai untuk itu yang dapat digunakan sebagai satuconst
-satunya pilihan adalah menggunakan a#define
dan membiarkan kompiler menggantinya sebagai input teks sebelum menafsirkan artinya.Jawaban:
Sangat penting untuk dicatat bahwa
const int
tidak tidak berperilaku identik di C dan C ++, sehingga sebenarnya beberapa keberatan terhadap hal itu yang telah disinggung dalam pertanyaan asli dan jawaban luas Peter Bloomfields ini tidak valid:const int
konstanta mengkompilasi nilai waktu dan dapat digunakan untuk menetapkan batas array, sebagai label kasus, dll.const int
konstanta tidak harus menempati penyimpanan apa pun. Kecuali Anda mengambil alamat mereka atau menyatakan mereka dari luar, mereka umumnya hanya akan memiliki waktu kompilasi.Namun, untuk konstanta integer, mungkin lebih baik menggunakan (dinamai atau anonim)
enum
. Saya sering suka ini karena:const int
(setiap bit sama amannya dengan di C ++ 11).Jadi dalam program C ++ idiomatik, tidak ada alasan apa pun untuk digunakan
#define
untuk mendefinisikan konstanta integer. Bahkan jika Anda ingin tetap kompatibel dengan C (karena persyaratan teknis, karena Anda menendang sekolah lama, atau karena orang yang bekerja dengan Anda lebih suka dengan cara itu), Anda masih dapat menggunakanenum
dan harus melakukannya, daripada menggunakannya#define
.sumber
const int
. Untuk jenis yang lebih kompleks, Anda benar bahwa penyimpanan mungkin dialokasikan, tetapi meskipun demikian, Anda tidak akan lebih buruk daripada dengan a#define
.EDIT: microtherion memberikan jawaban luar biasa yang mengoreksi beberapa poin saya di sini, khususnya tentang penggunaan memori.
Seperti yang telah Anda identifikasi, ada situasi tertentu di mana Anda dipaksa untuk menggunakan
#define
, karena kompiler tidak akan mengizinkanconst
variabel. Demikian pula, dalam beberapa situasi Anda dipaksa untuk menggunakan variabel, seperti ketika Anda membutuhkan array nilai (yaitu Anda tidak dapat memiliki array#define
).Namun, ada banyak situasi lain di mana tidak selalu ada satu jawaban 'benar'. Berikut adalah beberapa pedoman yang akan saya ikuti:
Jenis keamanan
Dari sudut pandang pemrograman umum,
const
variabel biasanya lebih disukai (jika memungkinkan). Alasan utama untuk itu adalah tipe-safety.A
#define
(preprocessor macro) secara langsung menyalin nilai literal ke setiap lokasi dalam kode, membuat setiap penggunaan independen. Ini secara hipotetis dapat mengakibatkan ambiguitas, karena jenisnya mungkin akan diselesaikan secara berbeda tergantung pada bagaimana / di mana ia digunakan.Sebuah
const
variabel hanya pernah satu jenis, yang ditentukan oleh deklarasi, dan diselesaikan selama inisialisasi. Ini akan sering membutuhkan pemeran eksplisit sebelum berperilaku berbeda (meskipun ada berbagai situasi di mana ia dapat secara aman dipromosikan secara tipe). Paling tidak, kompiler dapat (jika dikonfigurasi dengan benar) memancarkan peringatan yang lebih dapat diandalkan ketika masalah jenis terjadi.Solusi yang mungkin untuk ini adalah dengan memasukkan gips eksplisit atau tipe-suffix dalam a
#define
. Sebagai contoh:Pendekatan itu berpotensi menyebabkan masalah sintaksis dalam beberapa kasus, tergantung pada bagaimana itu digunakan.
Penggunaan memori
Tidak seperti komputasi untuk keperluan umum, memori jelas sangat mahal ketika berhadapan dengan sesuatu seperti Arduino. Menggunakan
const
variabel vs. a#define
dapat memengaruhi tempat data disimpan dalam memori, yang mungkin memaksa Anda untuk menggunakan satu atau lainnya.const
variabel akan (biasanya) disimpan dalam SRAM, bersama dengan semua variabel lainnya.#define
akan sering disimpan dalam ruang program (memori Flash), di samping sketsa itu sendiri.(Perhatikan bahwa ada berbagai hal yang dapat memengaruhi dengan tepat bagaimana dan di mana sesuatu disimpan, seperti konfigurasi dan optimisasi kompiler.)
SRAM dan Flash memiliki batasan berbeda (misalnya masing-masing 2 KB dan 32 KB untuk Uno). Untuk beberapa aplikasi, kehabisan SRAM sangat mudah, sehingga dapat membantu untuk memindahkan beberapa hal ke Flash. Kebalikannya juga mungkin, meskipun mungkin kurang umum.
PROGMEM
Memungkinkan untuk mendapatkan manfaat dari keamanan tipe sambil menyimpan data dalam ruang program (Flash). Ini dilakukan dengan menggunakan
PROGMEM
kata kunci. Itu tidak bekerja untuk semua jenis, tetapi itu biasanya digunakan untuk array bilangan bulat atau string.Bentuk umum yang diberikan dalam dokumentasi adalah sebagai berikut:
Tabel string sedikit lebih rumit, tetapi dokumentasi memiliki detail lengkap.
sumber
Untuk variabel dari tipe tertentu yang tidak diubah selama eksekusi, biasanya dapat digunakan.
Untuk nomor pin Digital yang terkandung dalam variabel, keduanya dapat berfungsi - seperti:
Tetapi ada satu keadaan di mana saya selalu menggunakan
#define
Ini untuk menentukan nomor pin analog, karena mereka alfanumerik.
Tentu, Anda bisa keras-kode nomor pin sebagai
a2
,a3
, dll di seluruh program dan compiler akan tahu apa yang harus dilakukan dengan mereka. Kemudian jika Anda mengganti pin maka setiap penggunaan perlu diubah.Selain itu, saya selalu ingin memiliki definisi pin saya di atas semua di satu tempat, jadi pertanyaannya menjadi jenis
const
pin yang sesuai untuk pin yang didefinisikanA5
.Dalam kasus itu saya selalu menggunakan
#define
Contoh Pembagi Tegangan:
Semua variabel pengaturan berada tepat di atas dan tidak akan pernah ada perubahan nilai
adcPin
kecuali pada waktu kompilasi.Jangan khawatir tentang jenis apa
adcPin
itu. Dan tidak ada RAM tambahan yang digunakan dalam biner untuk menyimpan konstanta.Kompilator hanya mengganti setiap instance
adcPin
dengan stringA5
sebelum kompilasi.Ada utas Arduino Forum yang menarik yang membahas cara-cara lain untuk memutuskan:
#define vs const variabel (forum Arduino)
Petuah:
Substitusi kode:
Kode debug:
Mendefinisikan
true
danfalse
sebagai Boolean untuk menghemat RAMBanyak yang turun ke preferensi pribadi, namun jelas bahwa
#define
itu lebih fleksibel.sumber
const
tidak akan menggunakan lebih banyak RAM daripada a#define
. Dan untuk pin analog, saya akan mendefinisikannya sebagaiconst uint8_t
, meskipunconst int
tidak ada bedanya.const
tidak benar-benar menggunakan lebih banyak RAM [...] sampai benar-benar digunakan ". Anda melewatkan poin saya: sebagian besar waktu, aconst
tidak menggunakan RAM, bahkan ketika itu digunakan . Kemudian, " ini adalah kompiler multipass ". Yang paling penting, ini adalah kompiler yang mengoptimalkan . Kapan pun memungkinkan, konstanta dioptimalkan menjadi operan langsung .