Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test for empty macro definition

Tags:

I've got a set of debug macros in tracing.hh. Whether it generates code and output is controlled by a macro flag in the real source code:

// File:  foo.cc #define TRACING 0 #include "tracing.hh" // Away we go . . . TRACEF("debug message"); 

The flag TRACING should have a value; I usually toggle between 0 and 1.

Within tracing.h,

  • #ifdef TRACING will tell me that tracing was defined.
  • #if TRACING controls the definition of functional macros like TRACEF()

But what if TRACING has no value? Then #if TRACING produces an error:

In file included from foo.c:3: tracing.hh:73:12: error: #if with no expression 

How can I test if TRACING is defined but has no value?

like image 656
pdbj Avatar asked Nov 04 '10 23:11

pdbj


People also ask

What does empty macro?

It is simply a macro that expands to, well, nothing.

How do I know if a macro is defined?

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

What do you mean by macro?

A macro is an automated input sequence that imitates keystrokes or mouse actions. A macro is typically used to replace a repetitive series of keyboard and mouse actions and used often in spreadsheets and word processing applications like MS Excel and MS Word. The file extension of a macro is commonly . MAC.

What is macro and its types?

A macro is a segment of code which is replaced by the value of macro. Macro is defined by #define directive. There are two types of macros: Object-like Macros. Function-like Macros.


2 Answers

With Matti's suggestion and some more poking, I think the issue is this: if TRACING has no value, we need a valid preprocessor expression in the test #if .... The Gnu cpp manual says it has to evaluate to an integer expression, so we need an expression that is valid even if one of the arguments is missing. What I finally hit on is:

#if (TRACING + 0) #  . . . 
  • If TRACING has a numerical value (as in #define TRACING 2 \n), cpp has a valid expression, and we haven't changed the value.
  • If TRACING has no value (as in #define TRACING \n), the preprocessor evaluates #if (+0) to false

The only case this doesn't handle is

  • If TRACING has a non-numerical value (i.e., ON). The cpp manual says "Identifiers that are not macros . . . are all considered to be the number zero," which evaluates to false. In this case, however, it would make more sense to consider this a true value. The only ones that do the right thing are the boolean literals true and false.
like image 191
pdbj Avatar answered Oct 27 '22 11:10

pdbj


Late to the party but I found a nice trick to distinguish

#define TRACING 0 

from

#define DTRACING 

like this:

#if (0-TRACING-1)==1 && (TRACING+0)!=-2 #error "tracing empty" #endif 

If TRACING is empty, the expression evaluates to 0--1 => 1.

If TRACING is 0, the expression evaluates to 0-0-1 => -1

I added an extra check in case TRACING==-2 which would make the first test pass.

This doesn't work for string literals of course.

like image 35
Jean-François Fabre Avatar answered Oct 27 '22 11:10

Jean-François Fabre