Câu trả lời:
Các trang trên cppreference.com trạng thái:
Sau khi tất cả mở rộng và đánh giá macro của các biểu thức được xác định và __has_include (kể từ C ++ 17), bất kỳ định danh nào không phải là chữ boolean đều được thay thế bằng số 0 (điều này bao gồm các định danh là từ khóa từ vựng, nhưng không phải là mã thông báo thay thế như và ).
Vì vậy, cả hai foo
và bar
được thay thế bằng 0.
Trong một #if
tuyên bố, bất kỳ định danh nào còn lại sau khi thay thế macro (ngoại trừ true
và false
) được thay thế bằng hằng số 0
. Vì vậy, chỉ thị của bạn trở thành
#if 0 == 0
cái nào đúng.
Điều này là do cả hai foo
cũng không bar
được đưa ra bất kỳ định nghĩa hoặc giá trị nào - vì vậy chúng giống nhau (nghĩa là được thay thế bằng giá trị "0"). Trình biên dịch sẽ đưa ra cảnh báo về điều này.
Trình MSVC
biên dịch (Visual Studio 2019) đưa ra các thông tin sau:
cảnh báo C4668: 'foo' không được định nghĩa là macro tiền xử lý, thay thế bằng '0' cho '# if / # elif'
cảnh báo C4668: 'bar' không được định nghĩa là macro tiền xử lý, thay thế bằng '0' cho '#if / # elif '
Vì vậy, VALUE
được đưa ra giá trị '0' (mặc định cho foo
) và bar
cũng có '0', do đó, VALUE == bar
đánh giá thành "TRUE".
Tương tự, clang-cl
đưa ra như sau:
cảnh báo: 'foo' không được xác định, đánh giá thành 0 [-Wundef]
cảnh báo: 'bar' không được xác định, ước tính thành 0 [-Wundef]
MSVC
và clang-cl
trình biên dịch, cảnh báo này có thể bị vô hiệu hóa (cụ thể hoặc bằng cách đặt 'mức' cảnh báo thích hợp).
Để thực hiện những gì bạn đang theo đuổi, hãy thử điều này:
#include <iostream>
#define DEBUG
int main() {
#ifdef DEBUG
std::cout << "WORKS!" << std::endl;
#endif
}
Trong trường hợp này, bạn có thể tắt các câu lệnh gỡ lỗi bằng cách thay đổi "xác định" thành "undef".
#include <iostream>
#undef DEBUG
int main() {
#ifdef DEBUG
std::cout << "WORKS!" << std::endl;
#endif
}
Bạn có thể thấy rằng trình biên dịch của bạn cho phép bạn xác định DEBUG bên ngoài mã, tại thời điểm đó bạn có thể giảm mã xuống
#include <iostream>
int main() {
#ifdef DEBUG
std::cout << "WORKS!" << std::endl;
#endif
}
Và sau đó gọi trình biên dịch với một tùy chọn như -DDEBUG = 0
Kiểm tra chương về Lập trình phòng thủ trong Steve McConnell, "Hoàn thành mã".