pmor
pmor

Reputation: 6286

C preprocessor: what is the motivation behind treating undefined macro as 0?

ISO/IEC 9899:202x (E) working draft — February 5, 2020 C17..C2x N2479:

After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers (including those lexically identical to keywords) are replaced with the pp-number 0, and then each preprocessing token is converted into a token.

In other words:

An identifier that is not defined as a macro is converted to 0 before the expression is evaluated.

This leads to the fact that UNDEFINED == 0 is true:

#if UNDEFINED == 0
#pragma message "UNDEFINED == 0 is true"
#endif
$ gcc t0.c -E
t0.c:3:9: note: '#pragma message: UNDEFINED == 0 is true'

However, how conceptually (logically, mathematically, philosophically, etc.) UNDEFINED can equal to 0 (leading to UNDEFINED == 0 is true)?

For example, in IEEE 754 the NaN can be seen as UNDEFINED (Not a Number, hence, there is no number, the number is not defined, i.e. undefined) and NaN == 0 is false:

#include <stdio.h>
#include <math.h>
int main( void )
{
    printf("NaN == 0 is %d\n", NAN == 0);
    return 0;
}
$ gcc t0.c && ./a.exe
NaN == 0 is 0

Question: What is the motivation behind treating in C preprocessor undefined macro as 0?

Upvotes: 4

Views: 1234

Answers (2)

pmor
pmor

Reputation: 6286

Correcting / answering to myself.

NaN (Not a Number) != undefined FP variable.

I.e. the FP variable (object) is defined, but its content is NaN.

If you try to compile a C program which uses NAN w/o including in advance math.h you'll get compile error (example is given for gcc): error: 'NAN' undeclared.

Hence, NaN cannot be seen as UNDEFINED.

User @dxiv correctly said:

this behavior (treating undefined macro as 0) does in fact simplify certain constructs

If you'd, for example, argue:

undefined macro shall lead to syntax error -- the preprocessor logic shall be changed

then I'd argue that in real already written code in case of undefined macro the frequency of syntax errors caused by missing #ifdef in front of #if will be much higher than the frequency of using #ifdef (with or w/o the following #if).

Hence, very possibly it was the reason that WG14 has decided to in case of undefined macro trade usability (i.e. allow use of #if w/o the leading #ifdef) over mathematical correctness (i.e. undefined macro shall lead to syntax error).

Upvotes: 1

dxiv
dxiv

Reputation: 17648

Question: What is the motivation behind treating in C preprocessor undefined macro as 0?

Emphasis on preprocessor. Undefined macros are treated as 0 by the preprocessor, but not by the compiler. For example, the following fails to compile:

#undef UNDEFINED
#if UNDEFINED == 0  // ok, preprocessor evaluates this as '0 == 0'
int n = UNDEFINED;  // error, compiler sees this as 'int n = <undeclared-identifier>;'
#endif

As with other idiosyncrasies, the real answer to the "why" question is "because the C language standard says so". While it is hard to track down the original motivations from decades ago, this behavior does in fact simplify certain constructs, for example the following is enough to check for C99 compliance, without having to worry whether the standard macro __STDC_VERSION__ is defined by the implementation or not:

#if __STDC_VERSION__ >= 199901L
// safely assume C99 or later
#else
// either __STDC_VERSION__ is not defined
// or it is earlier than C99
#endif

Upvotes: 10

Related Questions