cmacrosc-preprocessorconditional-compilationdefine-syntax

Cannot resolve function-like macro inside conditional compilation block


Consider the following - I want to check with #if #endif whether a token is defined somewhere in the code. I am using a CONCAT(input) macro that should glue the constant and changing parts of the token that I want to check.

Unfortunately, the approach presented below causes a compilation error:

error: missing binary operator before token "("


I have found the expressions that can be put inside a #if #endif block:

https://gcc.gnu.org/onlinedocs/cpp/If.html#If

And apparently it states that:

Macros. All macros in the expression are expanded before actual computation of the expression’s value begins.

It turns out that (CONCAT(test)) should be resolved, but it is not.

Is there any workaround allowing to resolve concatenated token names correctly in a conditional compilation block?

#include <stdio.h>

#define CONCAT(input) string##input
#define stringtest 1

int main(void) 
{
    #if defined(CONCAT(test)) && (CONCAT(test)==1)
        printf("OK");
    #else
        printf("NOT");
    #endif

    return 0;
}

Solution

  • If you use just: #if CONCAT(test) == 1 it will work and is enought. The statement #if defined(CONCAT(test)) does not work because CONCAT(test) will be evaluated to stringtest which will be evaluated to 1, and you can't use defined on a numerical constant.

    A different situation came to my mind - what if I want to check whether the token is eg. != 1 Then if it is not defined anywhere, the condition will evaluate to true. So there would be no difference between token not defined and token being different than 1.

    You could handle == 0 equal to not defined. So you could use: #if CONCAT(test) != 0 && CONCAT(test) != 1 where CONCAT(test) != 0 means defined(CONCAT(test)). That is the only alternative, because you can't get macro expansion work in a #ifdef or #if defined() statement, see this question which is very similar to yours.


    The gcc documentation says:

    Conditionals written like this: #if defined BUFSIZE && BUFSIZE >= 1024

    can generally be simplified to just #if BUFSIZE >= 1024, since if BUFSIZE is not defined, it will be interpreted as having the value zero.

    Also it can be helpful if you check macro expansion by using gcc -E yourSource.cpp.

    gcc --help:

    -E Preprocess only; do not compile, assemble or link