Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

For example

#define DEBUG_PRINT 1 

And then use it like

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

However, it comes a problem if the header file that contains the #define is forgotten to be included in the source code. Since the macro is not declared, the preprocessor treats it as if it equals 0, and the #if statement never runs.

When the header file is forgotten to be included, non-expected, unruly behaviour can occur.

Ideally, I would like to be able to both check that a macro is defined, and check that it equals a certain value, in one line. If it is not defined, the preprocessor throws an error (or warning).

I'm looking for something along the lines of:

#if-def-and-true-else-throw-error(DEBUG_PRINT)     ... #endif 

It's like a combination of #ifdef and #if, and if it doesn't exist, uses #error.

I have explored a few avenues, however, preprocessor directives can't be used inside a #define block, and 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.

like image 676
gbmhunter Avatar asked Jun 18 '13 04:06

gbmhunter


People also ask

How do you check if a macro is defined?

Inside of a C source file, you can use the #ifdef macro to check if a macro is defined.

Which of the following directive processor will return true if this macro is defined?

#ifdef: It returns true if a certain macro is defined. #ifndef: It returns true if a certain macro is not defined. #if, #elif, #else, and #endif: It tests the program using a certain condition; these directives can be nested too.

What are conditional macros?

A conditional expression defines the selection criteria for the different functions to be carried out in a macro group. A conditional expression is an expression that evaluates to a true or false value, and the appropriate function is processed based on that value.

Can you define a macro with another macro?

Short answer yes. You can nest defines and macros like that - as many levels as you want as long as it isn't recursive.


2 Answers

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.

like image 125
Michael Burr Avatar answered Oct 13 '22 01:10

Michael Burr


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++;) 
like image 24
Jim Balter Avatar answered Oct 13 '22 00:10

Jim Balter