[net.lang.c] #if foo vs #if defined

grt@twitch.UUCP ( G.R.Tomasevich) (06/25/86)

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() {}

if the 'cc' command includes either '-Dsquat' or '-Dfoo', then 'yes' is
selected, else 'no' is selected.  E.g.: 'cc -Dfoo -E c.c'
System: VAX-11/785 running UNIX 5.2
-- 
	George Tomasevich, ihnp4!twitch!grt
	AT&T Bell Laboratories, Holmdel, NJ

greg@utcsri.UUCP (Gregory Smith) (06/27/86)

In article <379@twitch.UUCP> grt@twitch.UUCP ( G.R.Tomasevich) writes:
>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() {}
>
>if the 'cc' command includes either '-Dsquat' or '-Dfoo', then 'yes' is
>selected, else 'no' is selected.  E.g.: 'cc -Dfoo -E c.c'
>System: VAX-11/785 running UNIX 5.2
>-- 

This seems very wrong to me. If foo is defined (as 1), and squat isn't,
shouldn't that come out as

#if squat||1

which should be rejected by the cpp as containing a non-constant ?

What if '#define squat 0' and '#define foo 0' ?? The expression
becomes 0||0 which is false.

This compiler here (4.2BSD) backs me up on the second point, but not
on the first ( i.e. the given example works ). Apparently any symbol in
a #if expression becomes '0'.

What if squat or foo are defined as something other than a constant?
This device cannot replace #if defined(a)|| defined(b) in general.

-- 
"Shades of scorpions! Daedalus has vanished ..... Great Zeus, my ring!"
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg

rbutterworth@watmath.UUCP (Ray Butterworth) (06/27/86)

> 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.

guido@mcvax.uucp (Guido van Rossum) (06/29/86)

In article <1063@watmath.UUCP> rbutterworth@watmath.UUCP writes:
>A CPP which silently takes undefined symbols to be 0 can be quite
>dangerous.  [lengthy example deleted]

While I agree with your reasoning (the example was quite amazing!), the
ANSI C standard declares that undefined identifiers must be made 0.
Probably too many people have used this feature so they can't break that
existing code :-(

Guido van Rossum, CWI, Amsterdam <guido@mcvax.uucp>

jso@edison.UUCP (07/07/86)

In article <379@twitch.UUCP>, grt@twitch.UUCP ( G.R.Tomasevich) writes:
> #if squat||foo
> 
> if the 'cc' command includes either '-Dsquat' or '-Dfoo', then 'yes' is
> selected, else 'no' is selected.  E.g.: 'cc -Dfoo -E c.c'
> 	George Tomasevich, ihnp4!twitch!grt

Fine, since -Dfoo is the same as '#define foo 1', but what about
#define	foo
or
#define	foo	something

Do either of these work with
#if	squat||foo
?  I doubt it, since the #if is a *numeric* if.

	John Owens @ General Electric Company	(+1 804 978 5726)
	edison!jso%virginia@CSNet-Relay.ARPA		[old arpa]
	edison!jso@virginia.EDU				[w/ nameservers]
	jso@edison.UUCP					[w/ uucp domains]
	{cbosgd allegra ncsu xanth}!uvacs!edison!jso	[roll your own]

ron@brl-sem.UUCP (07/12/86)

In article <379@twitch.UUCP>, grt@twitch.UUCP ( G.R.Tomasevich) writes:
> 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

Consider an optionally included definition

#define	SQUAT	0

If your code really wanted to check for this then the proper
test would be

#if defined(SQUAT) && (squat == 0)

to differentiate between undefined SQUAT and SQUAT defined but
equal to zero.