2

As I understand with the C preprocessor you can use #define in one of two ways:

  1. #define SOME_VAL 3.4159f
  2. #define SOME_FLAG

I am writing a library and I am using #defines to for the user to parse in settings to do with compilation. My problem is I need to know which of the two aforementioned cases has been used.

Example: #define DISABLE_FEATURE or #define DISABLE_FEATURE false.

Is there a way for me to distinguish these two or do I have to specify in documentation which to use?

Ebony Ayers
  • 350
  • 1
  • 3
  • 9
  • The usual case is that those macros don't have a value. That's what's checked with `#if defined(xxx)`, it doesn't matter if a value is defined or not, the existence itself makes `#if defined(xxx)` to become true. – πάντα ῥεῖ Jan 20 '21 at 07:13
  • `#ifdef xxx` or `#if defined xxx` or `#if defined(xxx)` – john Jan 20 '21 at 07:13
  • You can generate an error for the first (empty) define - will that suffice? – Adrian Mole Jan 20 '21 at 07:20
  • `#define HAS_VALUE_(m) sizeof(#m)>1` and then `#define HAS_VALUE(m) HAS_VALUE_(m)`. At this point, you can say `if constexpr (HAS_VALUE(SOME_FLAG))` and it will tell you if the flag is defined with a value or is defined to emptiness. – Raymond Chen Jan 20 '21 at 07:24

2 Answers2

5

do I have to specify in documentation which to use?

Technically no, you don't. But you should.

You can easily normalise on checking for false by doing this:

#ifndef DISABLE_FEATURE
#define DISABLE_FEATURE false
#endif

// later
#if DISABLE_FEATURE == false
...

Normalising on checking for definedness is a bit trickier because you cannot compare an empty macro with a value. But it is possible. You can use macro magic such as this (expansion magic borrowed from here):

#define DO_EXPAND(VAL)  VAL ## 1
#define EXPAND(VAL)     DO_EXPAND(VAL)

#if defined(DISABLE_FEATURE) \
    && (EXPAND(DISABLE_FEATURE) == false)
#undef DISABLE_FEATURE
#endif

// later
#ifdef DISABLE_FEATURE
...

I recommend instead to stick to one way and to document that. In particular I recommend checking for definedness, and to ignore the value entirely.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

You can check if a macro exists with e.g.

#if defined(SOME_FLAG)
...
#endif

See e.g. this macro conditional reference.


With that said, it's impossible to distinguish between an "empty" macro (like SOME_FLAG in your example) and a macro defined with the integer literal 0 as the replacemenent.

Also note that unless the macro can be evaluated by the preprocessor you can't compare its "value".

For something like DISABLE_FEATURE you can do something like

#if defined(DISABLE_FEATURE) || DISABLE_FEATURE != false
    // Feature *is* disabled
#else
    // Feature is not disabled
#endif
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • `#if !defined(DISABLE_FEATURE) || DISABLE_FEATURE == false` expands to `#if !true || == false` if `DISABLE_FEATURE` is defined as empty. That results in an error – eerorika Jan 20 '21 at 07:28