Is there a way to both check a macro is defined and it equals a certain value at the same time

前端 未结 6 1389
别跟我提以往
别跟我提以往 2020-12-15 17:39

I regularly use object-like preprocessor macros as boolean flags in C code to turn on and off sections of code.

For example

#define          


        
相关标签:
6条回答
  • 2020-12-15 18:12

    Yes you can check both:

    #if defined DEBUG  &&  DEBUG == 1
    #  define D(...) printf(__VA_ARGS__)
    #else
    #  define D(...)
    #endif
    

    In this example even when #define DEBUG 0 but it is not equal to 1 thus nothing will be printed.

    You can do even this:

    #if defined DEBUG  &&  DEBUG
    #  define D(...) printf(__VA_ARGS__)
    #else
    #  define D(...)
    #endif
    

    Here if you #define DEBUG 0 and then D(1,2,3) also nothing will be printed

    DOC

    0 讨论(0)
  • 2020-12-15 18:15
    #if 0 // 0/1
    #define DEBUG_PRINT printf("%s", "Testing")
    #else
    #define DEBUG_PRINT printf("%s")
    #endif
    

    So when "if 0" it'll do nothing and when "if 1" it'll execute the defined macro.

    0 讨论(0)
  • 2020-12-15 18:19

    as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.

    It can't be an error because the C standard specifies that behavior is legal. From section 6.10.1/3 of ISO C99 standard:

    After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers are replaced with the pp-number 0....

    As Jim Balter notes in the comment below, though, some compilers (such as gcc) can issue warnings about it. However, since the behavior of substituting 0 for unrecognized preprocessor tokens is legal (and in many cases desirable), I'd expect that enabling such warnings in practice would generate a significant amount of noise.

    There's no way to do exactly what you want. If you want to generate a compilation failure if the macro is not defined, you'll have to do it explicitly

    #if !defined DEBUG_PRINT
    #error DEBUG_PRINT is not defined.
    #endif
    

    for each source file that cares. Alternatively, you could convert your macro to a function-like macro and avoid using #if. For example, you could define a DEBUG_PRINT macro that expands to a printf call for debug builds but expands to nothing for non-debug builds. Any file that neglects to include the header defining the macro then would fail to compile.


    Edit:

    Regarding desirability, I have seen numerous times where code uses:

    #if ENABLE_SOME_CODE
    ...
    #endif
    

    instead of:

    #ifdef ENABLE_SOME_CODE
    ...
    #endif
    

    so that #define ENABLE_SOME_CODE 0 disables the code rather than enables it.

    0 讨论(0)
  • 2020-12-15 18:28

    Simply create a macro DEBUG_PRINT that does the actual printing:

    #define DEBUG_PRINT(n, str)    \
                                   \
      if(n == 1)                   \
      {                            \
        printf("%s", str);         \
      }                            \
      else if(n == 2)              \
      {                            \
        do_something_else();       \
      }                            \
                                   \
    #endif
    
    
    #include <stdio.h>
    
    int main()
    {
      DEBUG_PRINT(1, "testing");
    }
    

    If the macro isn't defined, then you will get a compiler error because the symbol is not recognized.

    0 讨论(0)
  • 2020-12-15 18:29

    Rather than using DEBUG_PRINT directly in your source files, put this in the header file:

    #if !defined(DEBUG_PRINT)
        #error DEBUG_PRINT is not defined
    #endif
    
    #if DEBUG_PRINT
        #define PrintDebug([args]) [definition]
    #else
        #define PrintDebug
    #endif
    

    Any source file that uses PrintDebug but doesn't include the header file will fail to compile.

    If you need other code than calls to PrintDebug to be compiled based on DEBUG_PRINT, consider using Michael Burr's suggestion of using plain if rather than #if (yes, the optimizer will not generate code within a false constant test).

    Edit: And you can generalize PrintDebug above to include or exclude arbitrary code as long as you don't have commas that look like macro arguments:

    #if !defined(IF_DEBUG)
        #error IF_DEBUG is not defined
    #endif
    
    #if IF_DEBUG
        #define IfDebug(code) code
    #else
        #define IfDebug(code)
    #endif
    

    Then you can write stuff like

    IfDebug(int count1;)  // IfDebug(int count1, count2;) won't work
    IfDebug(int count2;)
    ...
    IfDebug(count1++; count2++;)
    
    0 讨论(0)
  • 2020-12-15 18:37

    This may not work for the general case (I don't think there's a general solution to what you're asking for), but for your specific example you might consider changing this sequence of code:

    #if(DEBUG_PRINT == 1)
        printf("%s", "Testing");
    #endif
    

    to:

    if (DEBUG_PRINT == 1) {
        printf("%s", "Testing");
    }
    

    It's no more verbose and will fail to compile if DEBUG_PRINT is not defined or if it's defined to be something that cannot be compared with 1.

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