From: torek@horse.ee.lbl.gov (Chris Torek)
Newsgroups: comp.sys.sun.misc,comp.lang.c
Subject: Re: Strange error in C compiler
Date: 28 Aug 1992 10:56:06 GMT
Organization: Lawrence Berkeley Laboratory, Berkeley
Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
NNTP-Posting-Host: 128.3.112.15
Keywords: dynamic linking C compilation constant pointer

In article <13271.714953297@kiae.su> leo@ipmce.su writes:
>extern _DYNAMIC[];

Names beginning with an underscore followed by an uppercase letter
or another underscore are defined as ``reserved to the implementation''.
Thus, as far as the C language is concerned, the behavior of this (and
anything else in the program, given this) is undefined.

>main() {
>	if (_DYNAMIC)
>		puts("Dynamic");
>	else
>		puts("Static");
>}

>[The compiler completely eliminates the else clause as dead code; why?]

If we were to change this to

	#include <stdio.h>
	#include <stdlib.h>
	extern int A[];
	int main(void) {
		if (A)
			puts("Dynamic");
		else
			puts("Static");
		exit(0);
	}

and then compile it with a module that defines the array A[], we might
*expect* the compiler to omit the ``else'' clause (and, one hopes, warn
that the second puts() call is unreachable).  By definition, the ``value''
of an array object is the address of its first element, so this test is
identical to:

		if (&A[0] != NULL)

The C language guarantees that no ``normal'' pointer value, including
those arising from ``&object'' constructs, compares equal to NULL, so
this is logically equivalent to:

		if (1)

and the code in main() can therefore be rewritten as:

		puts("Dynamic");
		goto done;
		puts("Static");
	done:
		exit(0);

>... with if-statement rewritten as ``if (_DYNAMIC != (int*) 0)'' [the
>else clause is retained and the program functions as intended under
>SunOS].  Could anyone explain why?

Answering ``why'' questions is impossible in general.  A surface reason
is ``because the compiler is written that way''.  By using the name
``_DYNAMIC'' you have bought into ``undefined behavior'', and the
system can do as it pleases.  If it wants to eliminiate dead code based
only on syntax rather than ``logical'' consequences of ``if this were a
defined behavior and acted like other defined behaviors'', that is just
the way it goes.

This of course invites wondering why the compiler is written that way.
Only the compiler's author(s) can answer this.  Laziness?  Obstinacy?
A need to test _DYNAMIC in vendor library code?  A bug in the optimizer?
There are many possibilities, and there is no real point in speculation.

If you have some real need to test _DYNAMIC, you will have to execute
that test outside the scope of the C language.  Once you commit to
this, whatever works is fair game.  Of course, any dependence on
undocumented compiler behavior is an invitation to sorrow: your code
may fail under the next release.  You might want to stick with
something documented, such as an interface to assembler.  At least in
assembler, you can test absolute symbols without worrying about the
compiler optimizing it out.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov
Xref: sparky comp.sys.sun.misc:3954 comp.sys.sun.wanted:1360