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.