2010-02-09 33 views
12

Tôi cần một cách để xác định một FLAGS_IF vĩ mô (hoặc tương đương) sao cho# nếu 0 như một định nghĩa

FLAGS_IF(expression) 
<block_of_code> 
FLAGS_ENDIF 

khi biên dịch trong debug (ví dụ với một công tắc biên dịch cụ thể) biên dịch để

if (MyFunction(expression)) 
{ 
    <block_of_code> 
} 

trong khi trong phiên bản không dẫn đến bất kỳ hướng dẫn, chỉ vì nó là như thế này

#if 0 
    <block_of_code> 
#endif 

trong sự thiếu hiểu biết của tôi về vấn đề của C/C++ tiền xử lý Tôi không thể nghĩ ra bất kỳ cách ngây thơ nào (kể từ #define FLAGS_IF(x) #if 0 thậm chí không biên dịch) khi thực hiện việc này, bạn có thể trợ giúp không?

Tôi cần một giải pháp:

  • Không được sai lầm nếu */ đang có mặt bên trong <block_of_code>
  • chắc chắn sẽ tạo ra 0 hướng dẫn trong phiên bản thậm chí bên trong chức năng inline ở bất kỳ độ sâu (tôi đoán không bao gồm này ? if (false){<block_of_code>} phải)
  • là tiêu chuẩn phù hợp nếu có thể
+4

Trừ khi bạn đang biên dịch hoàn toàn mà không tối ưu hóa, 'if (false) {code}' không đặt bất kỳ thứ gì vào đầu ra. –

+0

Tôi nghĩ các trình biên dịch ít thông minh hơn thế. Cảm ơn – valerio

+10

Như một quy tắc chung, trình biên dịch thông minh hơn bạn. Có lẽ không ** bạn **, nhưng chắc chắn là tôi. –

Trả lời

12

Sau đây nên làm những gì bạn muốn:

#ifdef DEBUG 
# define FLAGS_IF(x) if (MyFunction((x))) { 
# define FLAGS_ENDIF } 
#else 
# define FLAGS_IF(x) if(0) { 
# define FLAGS_ENDIF } 
#endif 

Các if (0) nên biến thành không có hướng dẫn, hoặc ít nhất là nó làm như vậy trên hầu hết các trình biên dịch.

Sửa: Hasturkun nhận xét rằng bạn không thực sự cần các FLAGS_ENDIF, do đó bạn sẽ thay viết mã của bạn như thế này:

FLAGS_IF(expression) { 
    <block_of_code> 
} 

với các macro sau:

#ifdef DEBUG 
# define FLAGS_IF(x) if (MyFunction((x))) 
#else 
# define FLAGS_IF(x) if(0) 
#endif 
+1

Tôi đoán rằng valerio đang tìm kiếm một cách đơn giản để bật/tắt nhiều hơn chỉ một chức năng.Giải pháp của bạn không thể mở rộng và ẩn thực hiện thực. Giải pháp cho vấn đề này là sử dụng ifdef đơn giản. – eyalm

+0

Nếu đó là trường hợp tôi không thực sự cần một macro FLAGS_IF che giấu câu lệnh if. Tôi chỉ có thể sử dụng #define FLAGS_EXP (expression) 0 if (FLAGS_EXP (expression)) { } – valerio

2

Làm thế nào về một cái gì đó như thế này:

#ifdef DEBUG 
#define FLAGS_IF(expr, block) { if (MyFunction(expr)) block } 
#else 
#define FLAGS_IF(expr, block) 
#endif 

Bạn có thể sử dụng nó như thế này:

FLAGS_IF(your_favourite_expression, 
    ({ 
    // some code 
    }) 
) 
+0

Vâng, đây là cách tôi sẽ làm điều đó – joveha

+1

Tôi đã làm điều này và làm nổi bật cú pháp choke. Oh well. – Joshua

+0

Hm, làm việc tốt trong SlickEdit cho tôi; chưa thử nhiều người khác. –

4

Tại sao bạn không thể sử dụng sau đây?

 
#ifdef DEBUG 
code for debug mode 
#else 
code for release mode 
#endif 
+0

Tôi không thích điều này vì nó đòi hỏi nhiều mã sao chép, tôi thích đặt logic chuyển đổi bên trong vĩ mô – valerio

+0

Tôi không thực sự rõ ràng về cách này là khác nhau từ việc sử dụng một vĩ mô. Cho dù bạn #ifdef DEBUG hoặc bạn sử dụng macro thực tế, có vẻ như bạn sẽ có gần như cùng một lượng trùng lặp. Và việc sử dụng #ifdef DEBUG là cách phổ biến hơn để làm điều đó, vì vậy nhiều khả năng mọi người sẽ biết chính xác những gì bạn đang làm nhanh hơn, thay vì tạo ra vấn đề bảo trì. – atk

30

Macros là khá ác, nhưng không có gì xấu xa hơn obfuscating điều khiển báo cáo và các khối với các macro. Không có lý do chính đáng để viết mã như thế này. Chỉ cần làm cho nó:

#ifdef DEBUG 
    if (MyFunction(expression)) 
    { 
    <block_of_code> 
    } 
#endif 
+0

Tôi hoàn toàn đồng ý nhưng tôi không thể đủ khả năng để làm điều này mỗi lần. Một macro trong trường hợp này là khá hữu ích – valerio

+2

Tôi không nghĩ rằng giải pháp này là bất kỳ khác với một trong những bạn chấp nhận về cách gõ. –

+0

Một số khác cho phép tôi đính kèm #ifdef bên trong điều kiện – valerio

7

tôi có thể làm điều gì đó như:

#ifdef DEBUG 
const bool IS_RELEASE_MODE = false; 
#else 
const bool IS_RELEASE_MODE = true; 
#endif 

if (IS_RELEASE_MODE && MyFunction(expression)) 
{ 
    ... 
} 

này nên được biên soạn ra khỏi phát hành xây dựng do thực tế rằng nếu (false & & f()) là giống như if (false), được tối ưu hóa trong hầu hết các trình biên dịch.

Đó là nếu bạn khăng khăng không sử dụng #ifdef ở bên trong mã của bạn. Nếu không, tôi muốn sử dụng #ifdef DEBUG nếu (MyFunction (expression)) {...} #endif mà người khác đã đăng.

+0

Tôi cũng sẽ thử tính năng này – valerio

+0

+1 Chắc chắn tôi sẽ đi. Ngăn chặn địa ngục Macro và sẽ dẫn đến tối ưu hóa tương tự trên hầu hết các trình biên dịch hiện đại. – 0xC0DEFACE

3

Tôi thường cố gắng tránh sử dụng quá nhiều biên dịch có điều kiện khi có thể.

Đối với một, nó thường xấu xí và ít có thể đọc được.

Nhưng thậm chí đáng kể hơn, khi các dự án sử dụng trình biên dịch có điều kiện để bật mã gỡ lỗi trên & tắt, đôi khi tôi gặp phải sự cố khi mã gỡ lỗi bị tắt khi bị vô hiệu hóa. Sau đó, khi tôi muốn thực sự sử dụng nó mã gỡ lỗi, tôi bật nó lên và ... Mọi thứ. Đừng. Xây dựng. Nữa không.

Mã gỡ lỗi có thể tham chiếu các biến hoặc hàm không còn tồn tại, hoặc những thứ xung quanh mã gỡ lỗi tiềm ẩn đã thay đổi đủ để nó không còn hợp lệ nữa.

Nó có thể thực sự gây khó chịu. Vì vậy, cá nhân tôi đã thực hiện để tránh biên dịch có điều kiện để bật/tắt mã gỡ lỗi có lợi cho việc sử dụng một kiểu liệt kê hoặc macro (vẫn được biên dịch theo điều kiện) để sử dụng làm điều kiện trong câu lệnh if. Khi được biên dịch dưới dạng if (0), không có mã thời gian chạy nào được tạo - chính xác như mong muốn. Tuy nhiên, mã vẫn được biên dịch và kiểm tra cú pháp, vì vậy nó luôn ít nhất là cú pháp chính xác.

#if NDEBUG // using the same standard macro that `assert()` uses 
      // use your own if NDEBUG doesn't make sense 
enum { 
    DebugOn = 0 
} 
#else 
enum { 
    DebugOn = 1 
} 
#endif 


// ... elsewhere 

if (DebugOn) { 
    // this always gets compiled, but if it's a release build 
    // the compiler will not emit anything... 
} 

Như FryGuy mentioned, bạn có thể dễ dàng kết hợp với gọi MyFunction() của bạn nếu bạn thích - trong một thông cáo xây dựng, chức năng sẽ không được gọi là do chập mạch, đó là hành vi mà bạn chỉ định:

if (DebugOn && MyFunction(expression)) { 
    // this always gets compiled, but if it's a release build 
    // the compiler will not emit anything... 
} 

Nhưng cá nhân tôi, tôi có lẽ muốn sử dụng

if (DebugOn) { 
    if (MyFunction(expression)) { 
     // ... 
    } 
} 

mà tôi nghĩ giúp gọi ra một chút rõ ràng hơn (chỉ là một chút) rằng đây là một Debu khối g chỉ.

Điều này có những ưu điểm luôn được biên dịch và không có điều khiển luồng ẩn đằng sau các macro (một số câu trả lời khác đã được đề cập là ác).

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