1

Does anyone know how to, or if it's even possible to, create a variadic macro that expands to 0 if it's argument is not a defined macro, but expands to 1 if it's argument is a defined macro? (I'm using c99.)

#define BOB
#define SUE 45
#define IS_DEFINED(...) ???
IS_DEFINED(JOE)  <---- expands to 0
IS_DEFINED(BOB)  <---- expands to 1 (it's okay if this one doesn't work)
IS_DEFINED(SUE)  <---- expands to 1

EDIT: I specifically don't want any #if-related solutions... it needs to be a variadic macro (if that's possible) so I can do things like this:

#define CAT_(x, y) x ## y
#define CAT(x, y) CAT_(x, y)
#define CLEANUP0(...) ABC  <--- treats __VA_ARGS__ one way
#define CLEANUP1(...) XYZ  <--- treats __VA_ARGS__ a different way
#define CLEANUP(...) CAT(CLEANUP, IS_DEFINED(DEFAULT))(__VA_ARGS__)

Where ABC & XYZ are placeholders for other expansions that treat __VA_ARGS__ very differently.

textral
  • 1,029
  • 8
  • 13
  • 1
    `#if defined(JOE)`? – Shawn Mar 09 '21 at 12:54
  • 1
    I mean I don't get why, but if you want to use a variadic macro instead of `#ifdef` or `#if defined()` you could use a more powerful preprocessor like m4 to create macros that can have `#ifdef` in them perhaps. Seems a bit too overkill though. Is there any specific reason you need to do this, so maybe it would be easier to find a solution? – mediocrevegetable1 Mar 09 '21 at 12:57

1 Answers1

1

You can check whether a macro is defined with defined(), however this only works in the same circumstances where an #ifdef works (as far as I'm aware). I don't think this is possible but I might be mistaken.

Edit:

I don't know if this helps with what you want because the result will not be a constant expression. However if you want you could define the following macros:

#define _IS_DEFINED(...) (!!*#__VA_ARGS__)
#define IS_DEFINED(...) _IS_DEFINED(__VA_ARGS__)
#define BOB

if we now evaluate this we will get

int main() {
        printf("%d\n", IS_DEFINED(BOB));
}

which will give us

0

This is because IS_DEFINED(BOB) expands to (!!*""). In this case "" is just a pointer to some NUL byte in your .data section and dereferencing it will yield 0. But again, this is not a constant expression and as such the value is only avaliable to further usage in C and not the preprocessor. It also doesn't evaluate the second possibility as you wanted (like the example shows).

Leander
  • 35
  • 5
  • This is a good trick @Leander (one I know) but unfortunately I need the `0` or `1` at precompilation time. – textral Mar 09 '21 at 13:33
  • @DavidRanieri No, I needed a logical identity in order to get a 1 for all possible char values except `NUL`. If you just care about the logical value you could also just leave the negations out. – Leander Mar 09 '21 at 13:57