2016-08-19 29 views
12

tôi nghĩ về điều kiện và trình biên dịch. Tôi đang lập trình một ứng dụng cho Arduino và vì vậy tôi cần ứng dụng càng nhanh càng tốt.Compiler: Nếu tình trạng luôn luôn là đúng/sai

Trong mã của tôi, tôi có điều này:

#define DEBUG false  

... 

if (DEBUG) 
{ 
    String pinName; 
    pinName = "Pin "; 
    pinName += pin; 
    pinName += " initialized"; 
    Serial.println(pinName); 
} 

tôi tự hỏi nếu trình biên dịch không bao gồm mã (mã nhập nếu khối) trong tập tin nhị phân. Các điều kiện luôn luôn là sai, vì vậy chương trình không bao giờ đến đó.

Và từ phía bên kia. Điều gì xảy ra nếu DEBUG là đúng? Arduino có kiểm tra điều kiện hay trình biên dịch chỉ bao gồm phần thân của tập tin nhị phân không?

Tôi tìm thấy trang web này https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_4.html về chỉ thị #if, vì vậy tôi có thể viết lại mã để có các chỉ thị này thay vì "bình thường" nếu. Nhưng tôi muốn biết nếu tôi nên viết lại nó hoặc nếu nó sẽ lãng phí thời gian.

+3

Trình biên dịch thông minh sẽ thực hiện tối ưu hóa và sẽ không bao gồm mã nhị phân nếu 'DEBUG' là' false'. –

+7

'if (CONSTANT) {...}' rất dễ dàng cho trình biên dịch để tối ưu hóa. Tôi hy vọng rằng bất kỳ trình biên dịch tốt từ ít nhất 25 năm qua sẽ có thể loại bỏ nhánh có điều kiện. – Phylogenesis

+4

Tôi muốn sử dụng '# if' /' # endif', ngay cả khi nó không tạo sự khác biệt trong nhị phân. Bằng cách đó, rõ ràng 'DEBUG' là gì. – LogicStuff

Trả lời

8

Bất kỳ trình biên dịch nửa phong nha tối ưu hóa sẽ loại bỏ toàn bộ mã bên trong câu lệnh if, nếu nó có thể nói tại thời gian biên dịch rằng tình trạng này luôn luôn là false. Tương tự như vậy, bất kỳ trình biên dịch nửa phong nha nào cũng sẽ bỏ qua kiểm tra nếu điều kiện luôn đúng.

Quả thực đây là hoàn toàn tương đương với "công tắc biên dịch" như:

#define DEBUG 


#ifdef DEBUG 
... 
#endif 

Các "trình biên dịch chuyển" cú pháp với #ifdef là thích, vì nó làm cho mục đích rõ ràng hơn để các lập trình viên C khác. Nhưng đó chỉ là vấn đề về phong cách mã hóa - nó sẽ dẫn đến cùng một nhị phân như mã ban đầu của bạn.

1

Mã bạn đã viết không bao giờ được thực hiện, tuy nhiên, nó có thể có sẵn trong thực thi.

Tôi sẽ nói rằng trình biên dịch sẽ được yêu cầu để giữ mã này khi bạn vô hiệu hóa tối ưu hóa (như thêm -O0 vào Clang và GCC). Trong mọi trường hợp khác, tôi hy vọng rằng trình biên dịch sẽ loại bỏ các mã như đây là một tối ưu hóa rất đơn giản với một hiệu ứng kích thước mã đáng chú ý. Ví dụ, GCC loại bỏ điều này tại -O và cao hơn. (Xem manual)

Mặc dù, có 2 cách khác để viết mã của bạn, mà sẽ thực thi đoạn mã này không được bao gồm:

  • điều kiện Preprocessor
  • constexpr nếu

Bằng cách sử dụng các điều kiện tiền xử lý, bạn sẽ có thể loại bỏ mã trước khi nó đạt đến trình biên dịch thực tế. Nó có thể là một chút xâm nhập cho indenting của bạn, mặc dù nó sẽ làm việc với tất cả các trình biên dịch và các phiên bản từ các tiêu chuẩn C và C++.

#ifdef DEBUG 
    { // Optional: Adding extra scope to prevent usage of local variables after the endif 
    // Code to eliminate 
    } 
#endif 

Tuy nhiên, nếu bạn đang sử dụng C++ 17, bạn cũng có thể sử dụng constexpr if. Điều này sẽ ít xâm nhập vào mã của bạn và mặc dù mã trong câu lệnh if phải có cú pháp chính xác, nhưng nó không phải biên dịch (vì vậy không đúng ngữ nghĩa).

này có thể được viết như sau:

if constexpr (DEBUG) 
{ 
    // Code to eliminate 
} 
+0

là nó 'nếu constexpr'? – RiaD

+0

Không, nó là 'constexpr if'. Tôi đã thêm một liên kết vào đề xuất trong thư trả lời của tôi. – JVApen

+0

Tôi tin rằng nó đã lỗi thời http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0292r1.html https://herbsutter.com/2016/06/30/trip-report- summer-iso-c-standards-meeting-oulu/ – RiaD

0

Tôi không thích trả lời câu hỏi của riêng tôi, bởi vì tôi sẽ không tìm nó ra mà không cần sự giúp đỡ của bạn, guys.

Dù sao, tùy chọn đầu tiên là sử dụng:

#if DEBUG == true 
#endif 

hoặc

#ifdef DEBUG 
#endif 

trình biên dịch không nhận được mã trong # if/#ifdef (preprocessor loại bỏ nó), vì vậy nếu có một vấn đề trong phần mã này, không ai biết về nó nếu DEBUG được đặt thành false hoặc không được xác định (nhờ @Klaus).

tùy chọn thứ hai:

#define DEBUG false  

... 

if (DEBUG) 
{ 
    ... 
} 

Bất kỳ trình biên dịch mới nên loại bỏ các 'nếu' khối nếu điều kiện là sai hoặc loại bỏ các 'nếu' tuyên bố và rời khỏi cơ thể nếu điều kiện là đúng.

Vì vậy, tôi sẽ nói rằng đó là lập trình viên tiếp cận các bộ tốt hơn nhu cầu của ứng dụng.

Cách tiếp cận đầu tiên tốt hơn nếu bạn cần chắc chắn mã sẽ không được đưa vào nhị phân.

Cách tiếp cận thứ hai tốt hơn nếu bạn muốn trình biên dịch kiểm tra toàn bộ mã mỗi khi bạn biên dịch chương trình.

Nếu bạn thích câu trả lời này, hãy bỏ phiếu cho nó và tôi sẽ chấp nhận nó - nếu không ai cung cấp câu trả lời hay hơn.

+0

'#if DEBUG == true' có thể được thay thế bằng' #if DEBUG'. Tùy chọn khác là '#ifdef DEBUG'. Đối với một số định nghĩa như các tùy chọn thư viện, bạn có thể sử dụng kiểu '# if', nhưng đặc biệt đối với' DEBUG' thì tốt hơn nên sử dụng cú pháp '# ifdef'. – i486

Các vấn đề liên quan