Perbandingan makro jika-direktif


25

Mengapa #ifkondisi dalam kode berikut terpenuhi:

#include <iostream>
#define VALUE foo    

int main() {    
#if VALUE == bar
    std::cout << "WORKS!" << std::endl;
#endif // VALUE
}

Jawaban:


26

The halaman di cppreference.com negara:

Setelah semua ekspansi makro dan evaluasi ekspresi yang didefinisikan dan __has_include (karena C ++ 17), pengidentifikasi apa pun yang bukan boolean literal diganti dengan angka 0 (ini termasuk pengidentifikasi yang merupakan kata kunci leksikal, tetapi bukan token alternatif seperti dan ).

Jadi keduanya foodan bardiganti dengan 0.


Bagaimana dengan C ++ 98, C ++ 03, C ++ 11 dan C ++ 14?
— kelalaka

1
@kalalaka Semuanya sama saja. Sudah seperti itu sejak C89.
— SS Anne

1
@kelalaka Bagian "sejak C ++ 17" hanya mengacu pada bagian "dan __has_include". Sebelum C ++ 17 itu sama, hanya saja bagian itu dihilangkan.
— BessieTheCow

15

Dalam sebuah #ifpernyataan, setiap pengidentifikasi yang tetap setelah substitusi makro (kecuali untuk truedan false) diganti dengan konstanta 0. Jadi arahan Anda menjadi

#if 0 == 0

yang mana yang benar.


Untuk memperjelas, '#define VALUE foo' mendefinisikan simbol 'VALUE' untuk menyelesaikan ke nilai yang sama dengan simbol 'foo', tetapi simbol 'foo' tidak memiliki arti, sehingga akan ditafsirkan sebagai 0.
— ManicDee

14

Ini karena keduanya belum foojuga bardiberikan definisi atau nilai - sehingga keduanya sama (yaitu diganti dengan nilai "0"). Compiler akan memberi peringatan tentang hal ini.

The MSVCcompiler (Visual Studio 2019) memberikan berikut:

peringatan C4668: 'foo' tidak didefinisikan sebagai makro preprosesor, diganti dengan '0' untuk '# if / # elif'
peringatan C4668: 'bar' tidak didefinisikan sebagai makro praprosesor, diganti dengan '0' untuk '#jika / # elif '

Jadi VALUEdiberi nilai '0' (default untuk foo) dan barjuga memiliki '0', jadi VALUE == bardievaluasi menjadi "BENAR."

Demikian pula, clang-clberikan yang berikut:

peringatan: 'foo' tidak didefinisikan, mengevaluasi ke 0 [-Wundef]
peringatan: 'bar' tidak didefinisikan, mengevaluasi ke 0 [-Wundef]


Apakah peringatan itu wajib atau itu adalah fitur dari kompiler?
— kelalaka

1
@kelalaka Sepengetahuan saya, tidak ada 'peringatan' kompiler wajib! Bahkan dengan MSVCdan clang-clpenyusun, peringatan ini dapat dinonaktifkan (baik secara khusus, atau dengan menetapkan 'level' peringatan yang sesuai).
— Adrian Mole

0

Untuk mencapai apa yang Anda kejar, coba ini:

#include <iostream>
#define DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

Dalam hal ini Anda dapat mematikan pernyataan debugging dengan mengubah "define" menjadi "undef".

#include <iostream>
#undef DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

Anda mungkin menemukan bahwa kompiler Anda memungkinkan Anda untuk mendefinisikan DEBUG di luar kode itu sendiri, di mana Anda dapat mengurangi kode tersebut

#include <iostream>

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

Dan kemudian memanggil kompiler dengan opsi seperti -DDEBUG = 0

Lihatlah bab tentang Pemrograman Defensif di Steve McConnell, "Kode Lengkap."

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.