admin管理员组

文章数量:1277273

The following code compiles without error:

//#define FOO
#if FOO
    sdjlfs
#endif

int main(){
    return 0;
}

although I would expect it to fail at line 2, because the following doesn't compile (first line uncommented:

#define FOO
#if FOO
    sdjlfs
#endif

int main(){
    return 0;
}

I would get the following error:

error: #if with no expression
    2 | #if FOO
      |        ^

So why does the first case have an expression for FOO, and what would that value be? More generally, is it possible to differentiate whether something was defined with vs without a value?

#ifdef and its equivalent #if defined ... wouldn't suffice, because they alone only test if something is defined, they don't differentiate with vs without a value, and the following is pointless:

#ifdef FOO
    #if FOO == 1
       ...
    #endif
#endif

because the 2nd line would still fail if FOO is defined but without a value.

The following code compiles without error:

//#define FOO
#if FOO
    sdjlfs
#endif

int main(){
    return 0;
}

although I would expect it to fail at line 2, because the following doesn't compile (first line uncommented:

#define FOO
#if FOO
    sdjlfs
#endif

int main(){
    return 0;
}

I would get the following error:

error: #if with no expression
    2 | #if FOO
      |        ^

So why does the first case have an expression for FOO, and what would that value be? More generally, is it possible to differentiate whether something was defined with vs without a value?

#ifdef and its equivalent #if defined ... wouldn't suffice, because they alone only test if something is defined, they don't differentiate with vs without a value, and the following is pointless:

#ifdef FOO
    #if FOO == 1
       ...
    #endif
#endif

because the 2nd line would still fail if FOO is defined but without a value.

Share Improve this question edited Feb 24 at 11:16 mo FEAR asked Feb 24 at 11:10 mo FEARmo FEAR 7017 silver badges9 bronze badges 0
Add a comment  | 

3 Answers 3

Reset to default 4

Any preprocessor token passed to #if which results in an unknown identifier is replaced by a zero.

  • If you don't #define FOO, then FOO results in zero.
  • If you #define FOO then it expands, in this case to nothing, leaving the #if condition empty.

In case the intention is to do something similar to if (identifier) where anything non-zero is taken as a boolean "true", then you will have to do some trick like this:

#if defined(FOO) && (FOO+0)

  • If you don't #define FOO then the defined evaluates to false.
  • If you #define FOO and leave it empty, (FOO+0) gets preprocessed into (+0), a zero with the unary + operator in front - a valid integer constant expression evaluating to zero.
  • If you #define FOO (value) (note the space between macro name and contents), then it gets preprocessed into ((value)+0), where + is the binary + operator.

When evaluating the expression in an #if preprocessor statement, any identifier1 that is present after macro expansion is replaced by 0. So if there is no macro FOO defined in #if FOO, no macro expansion will occur, and this will become just #if 0


1Except for the special keyword defined, which will have its effect occur before macro expansion. Any defined that is still in the expression after macro expansion will cause undefined behavior

#if FOO checks if FOO was defined and if FOO is non zero (and is very important here)

  • first version of your code - FOO is not defined and the preprocessor does not check its value (shorthand evaluation)
  • The second version defines FOO and the preprocessor tries to get its value - but none was defined - thus, an error.

The only way to check if the FOO as numeric value (if you know the minimum value)

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MINVALUE 0
// example macros
#define FOO          // empty define
//#define FOO 1      // uncomment to test with value 1

int main(void) {
#if defined(FOO)
    // Check if FOO is empty or not
    #if (FOO + 1) > MINVALUE
        printf("FOO defined and equals larger than MINVALUE\n");
    #else
        printf("FOO defined but not larget than MINVALUE (or empty)\n");
    #endif
#else
    printf("FOO is not defined\n");
#endif

    // To show the actual content of FOO:
#ifdef FOO
    printf("FOO is defined as: '%s'\n", STR(FOO));
#endif

    return 0;
}

本文标签: cwhy does this compile amp how to test if a macro is defined with vs without a valueStack Overflow