#ifdef vs #if - which is better/safer as a method for enabling/disabling compilation of particular sections of code?

后端 未结 19 778
忘了有多久
忘了有多久 2020-11-30 17:26

This may be a matter of style, but there\'s a bit of a divide in our dev team and I wondered if anyone else had any ideas on the matter...

Basically, we have some de

相关标签:
19条回答
  • 2020-11-30 18:02

    I like #define DEBUG_ENABLED (0) when you might want multiple levels of debug. For example:

    #define DEBUG_RELEASE (0)
    #define DEBUG_ERROR (1)
    #define DEBUG_WARN (2)
    #define DEBUG_MEM (3)
    #ifndef DEBUG_LEVEL
    #define DEBUG_LEVEL (DEBUG_RELEASE)
    #endif
    //...
    
    //now not only
    #if (DEBUG_LEVEL)
    //...
    #endif
    
    //but also
    #if (DEBUG_LEVEL >= DEBUG_MEM)
    LOG("malloc'd %d bytes at %s:%d\n", size, __FILE__, __LINE__);
    #endif
    

    Makes it easier to debug memory leaks, without having all those log lines in your way of debugging other things.

    Also the #ifndef around the define makes it easier to pick a specific debug level at the commandline:

    make -DDEBUG_LEVEL=2
    cmake -DDEBUG_LEVEL=2
    etc
    

    If not for this, I would give advantage to #ifdef because the compiler/make flag would be overridden by the one in the file. So you don't have to worry about changing back the header before doing the commit.

    0 讨论(0)
  • 2020-11-30 18:03

    My initial reaction was #ifdef, of course, but I think #if actually has some significant advantages for this - here's why:

    First, you can use DEBUG_ENABLED in preprocessor and compiled tests. Example - Often, I want longer timeouts when debug is enabled, so using #if, I can write this

      DoSomethingSlowWithTimeout(DEBUG_ENABLED? 5000 : 1000);
    

    ... instead of ...

    #ifdef DEBUG_MODE
      DoSomethingSlowWithTimeout(5000);
    #else
      DoSomethingSlowWithTimeout(1000);
    #endif
    

    Second, you're in a better position if you want to migrate from a #define to a global constant. #defines are usually frowned on by most C++ programmers.

    And, Third, you say you've a divide in your team. My guess is this means different members have already adopted different approaches, and you need to standardise. Ruling that #if is the preferred choice means that code using #ifdef will compile -and run- even when DEBUG_ENABLED is false. And it's much easier to track down and remove debug output that is produced when it shouldn't be than vice-versa.

    Oh, and a minor readability point. You should be able to use true/false rather than 0/1 in your #define, and because the value is a single lexical token, it's the one time you don't need parentheses around it.

    #define DEBUG_ENABLED true
    

    instead of

    #define DEBUG_ENABLED (1)
    
    0 讨论(0)
  • 2020-11-30 18:03

    It's a matter of style. But I recommend a more concise way of doing this:

    #ifdef USE_DEBUG
    #define debug_print printf
    #else
    #define debug_print
    #endif
    
    debug_print("i=%d\n", i);
    

    You do this once, then always use debug_print() to either print or do nothing. (Yes, this will compile in both cases.) This way, your code won't be garbled with preprocessor directives.

    If you get the warning "expression has no effect" and want to get rid of it, here's an alternative:

    void dummy(const char*, ...)
    {}
    
    #ifdef USE_DEBUG
    #define debug_print printf
    #else
    #define debug_print dummy
    #endif
    
    debug_print("i=%d\n", i);
    
    0 讨论(0)
  • 2020-11-30 18:03

    I've always used #ifdef and compiler flags to define it...

    0 讨论(0)
  • 2020-11-30 18:04

    I myself prefer:

    #if defined(DEBUG_ENABLED)
    

    Since it makes it easier to create code that looks for the opposite condition much easier to spot:

    #if !defined(DEBUG_ENABLED)
    

    vs.

    #ifndef(DEBUG_ENABLED)
    
    0 讨论(0)
  • 2020-11-30 18:05

    They're both hideous. Instead, do this:

    #ifdef DEBUG
    #define D(x) do { x } while(0)
    #else
    #define D(x) do { } while(0)
    #endif
    

    Then whenever you need debug code, put it inside D();. And your program isn't polluted with hideous mazes of #ifdef.

    0 讨论(0)
提交回复
热议问题