Trong C / C ++
Điều gì xảy ra với mã được đặt giữa một #if 0
/ #endif
khối?
#if 0
//Code goes here
#endif
Có phải mã chỉ bị bỏ qua và do đó không được thực thi?
Trong C / C ++
Điều gì xảy ra với mã được đặt giữa một #if 0
/ #endif
khối?
#if 0
//Code goes here
#endif
Có phải mã chỉ bị bỏ qua và do đó không được thực thi?
Câu trả lời:
Nó không chỉ không được thực thi mà thậm chí còn không được biên dịch.
#if
là một lệnh tiền xử lý, được đánh giá trước bước biên dịch thực sự. Mã bên trong khối đó không xuất hiện trong tệp nhị phân đã biên dịch.
Nó thường được sử dụng để xóa tạm thời các đoạn mã với ý định bật lại chúng sau này.
Nó giống hệt với việc bình luận khối, ngoại trừ một điểm khác biệt quan trọng: Lồng không phải là một vấn đề. Hãy xem xét mã này:
foo();
bar(x, y); /* x must not be NULL */
baz();
Nếu tôi muốn bình luận nó ra, tôi có thể thử:
/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/
Bzzt. Lỗi cú pháp! Tại sao? Bởi vì các bình luận khối không lồng vào nhau, và do đó (như bạn có thể thấy từ tô sáng cú pháp của SO) */
sau từ "NULL" kết thúc bình luận, khiến baz
cuộc gọi không nhận xét ra ngoài và */
sau baz
một lỗi cú pháp. Mặt khác:
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
Hoạt động để bình luận ra toàn bộ sự việc. Và các #if 0
s sẽ lồng vào nhau, như vậy:
#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif
Mặc dù tất nhiên điều này có thể hơi khó hiểu và trở thành vấn đề đau đầu về bảo trì nếu không được nhận xét đúng cách.
foo.c:3: unterminated string or character constant
từ gcc, bạn đang sử dụng cái gì vậy?
Chính xác thì khối #if 0… #endif làm gì?
Nó cho bạn biết rằng tác giả rõ ràng là chưa bao giờ nghe nói về hệ thống kiểm soát phiên bản. Đến lượt nó, nó yêu cầu bạn chạy càng xa càng tốt…
Khi bộ xử lý tiền xử lý thấy # nếu nó sẽ kiểm tra xem mã thông báo tiếp theo có giá trị khác 0 hay không. Nếu có, nó sẽ giữ mã cho trình biên dịch. Nếu không, nó sẽ loại bỏ mã đó để trình biên dịch không bao giờ nhìn thấy nó.
Nếu ai đó nói #if 0, họ đang bình luận hiệu quả về mã nên nó sẽ không bao giờ được biên dịch. Bạn có thể nghĩ về điều này giống như thể họ đã đặt / * ... * / xung quanh nó. Nó không hoàn toàn giống nhau, nhưng nó có tác dụng tương tự.
Nếu bạn muốn hiểu những gì đã xảy ra một cách chi tiết, bạn có thể thường xuyên xem. Nhiều trình biên dịch sẽ cho phép bạn xem các tệp sau khi bộ xử lý trước đã chạy. Ví dụ, trên Visual C ++, lệnh switch / P sẽ thực thi bộ tiền xử lý và đưa kết quả vào tệp .i.
#if WIN32 || __CYGWIN__
nhưng điều này không hoạt động như mong đợi.
Các dòng bắt đầu bằng a #
là các chỉ thị tiền xử lý . #if 0 [...] #endif
các khối không đến được trình biên dịch và sẽ không tạo ra mã máy.
Bạn có thể chứng minh điều gì xảy ra với bộ tiền xử lý bằng tệp nguồn ifdef.cxx
:
#if 0
This code will not be compiled
#else
int i = 0;
#endif
Đang chạy gcc -E ifdef.cxx
sẽ hiển thị cho bạn những gì được biên dịch.
Bạn có thể chọn sử dụng cơ chế này để ngăn chặn một khối mã được biên dịch trong chu kỳ phát triển, nhưng có thể bạn sẽ không muốn kiểm tra nó trong phần kiểm soát nguồn của mình vì nó chỉ làm tăng thêm lỗi cho mã của bạn và làm giảm khả năng đọc. Nếu đó là một đoạn mã lịch sử đã được nhận xét, thì nó nên được loại bỏ: kiểm soát nguồn chứa lịch sử, phải không?
Ngoài ra, câu trả lời có thể giống nhau cho cả C và C ++ nhưng không có ngôn ngữ nào được gọi là C / C ++ và bạn không phải là một thói quen tốt khi đề cập đến một ngôn ngữ như vậy.
Không hẳn
int main(void)
{
#if 0
the apostrophe ' causes a warning
#endif
return 0;
}
Nó hiển thị "tc: 4: 19: warning: thiếu ký tự" terminating "với gcc 4.2.4
Đó là một cách bình luận rẻ tiền, nhưng tôi nghi ngờ rằng nó có thể có khả năng gỡ lỗi. Ví dụ: giả sử bạn có một bản dựng xuất ra các giá trị cho một tệp. Bạn có thể không muốn điều đó trong phiên bản cuối cùng để bạn có thể sử dụng #if 0 ... #endif.
Ngoài ra, tôi nghi ngờ một cách tốt hơn để làm điều đó cho mục đích gỡ lỗi sẽ là:
#ifdef DEBUG
// output to file
#endif
Bạn có thể làm điều gì đó như vậy và nó có thể có ý nghĩa hơn và tất cả những gì bạn phải làm là xác định GỠ LỖI để xem kết quả.
//
hoặc bắt đầu phần bằng/*
và kết thúc phần bằng*/
. Vấn đề với các kỹ thuật thứ hai là nhận xét không lồng vào nhau, vì vậy nhà phát triển phải kiểm tra và xử lý bất kỳ phần nào*/
giữa đầu và cuối.