#if foo vs #if defined(foo)

Ray Butterworth rbutterworth at watmath.UUCP
Sat Jun 28 05:46:03 AEST 1986


> Our compiler does not need a defined(), or at least I did not try whether
> it is even accepted.  The following example works fine:
> 
> #if squat||foo
> int yes;
> #else
> int no;
> #endif
> main() {}

A CPP which silently takes undefined symbols to be 0 can be quite
dangerous.  Consider the following case with these definitions
in a header file.

#define squat 10
#define foo 3 /* set to 0 if we don't want to process foos */

Now foo is defined and things work just the way they were intended to.
But suppose a year later, a change must be made because in a completely
different section of code we now want to handle dynamic foos, and so
the definition of foo can no longer be a fixed 3, but must be
#define foo (3*y)
extern int y;
where "y" is an external int which either contains 0, 1, 2, or 3.
Now to the person making this change there doesn't seem to be anything
wrong with it, as he is innocently unaware of the "#if squat||foo"
buried thousands of lines of code away.  But what happens when CPP
processes this "#if squat||foo" line?  CPP will expand this to
"#if squat||(3*y)".
A broken CPP, such as was recommended, would decide that the undefined
token "y" should be 0 and thus produce the "no" case regardless of the
value of the external int "y".  This is clearly not what the person
making the change wanted to happen, nor is it what the person originally
writing the "#if" wanted to happen.  How long will it be before this
newly introduded bug is detected, and how long will it take for someone
to figure out what has gone wrong?  Possibly a long time if this "#if"
is in a seldom-used section of code.

A reasonable CPP would would have issued an error that the token "y"
is undefined.  The problem would have been detected almost immediately
and certainly before anything was installed since the code no longer
compiles.  It would have shown where the problem was, and it would
have been trivial for the person making the change to turn the
"#if" into a "if(".  (Well not in this case since the "int no" isn't
executable, but you get the idea I hope.)

I think the effort of having to use "#ifdef x" or "#if defined(x)"
instead of lazily using "#if x" is well worth it.



More information about the Comp.lang.c mailing list