__STDC__ and non-conforming ANSI C compilers

T. William Wells bill at twwells.uucp
Sun Jan 22 07:38:35 AEST 1989


In article <9405 at smoke.BRL.MIL> gwyn at brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
:                             "Rough ANSI compliance" is meaningless
: and useless to the portable application programmer.  "Strict ANSI
: compliance", on the other hand, is a meaningful notion of considerable
: utility to the programmer.  In order for it to HAVE this utility,
: though, we need the symbol __STDC__ reserved for making the distinction.

This is the key to the disagreement: you believe that "Rough ANSI
compliance" is "useless to the portable application programmer".
Others do not.

While it is certainly true that an "almost" ANSI compiler can differ
from the standard in any arbitrary way, I suggest that many such will
often differ in uninteresting ways, or in ways that are easily dealt
with.

If this is the case (and the current situation seems to indicate that
is how things will be), the "almost" ANSI compiler will be in much the
same kind of class as one for BSD or SYSV, that is to say, one which
has a core of common features but irritating differences from those
in the class, and significant differences from those outside the
class.

In other words, "almost" ANSI would leave us in exactly the same
situation we have now, but with one more common environment to deal
with.

For those who don't mind (or don't understand) the current situation,
adding one more class of environments isn't likely to cause any
perceived hardship. For those that do, doing so is like going back to
the stone ages.

On the other hand, those who want some way of discovering "almost"
ANSI compliance have a valid point. Strictly speaking, if I run cc
-D..., the compiler is no longer conforming; thus, the compiler ought
not define __STDC__. Of course, there is nothing *preventing* the
compiler writer from simply documenting that using certain compiler
switches makes the compiler non-conforming, and leaving it at that.

But if we do that latter, we defile the "purity" of __STDC__.  But if
we don't, we can't have programs whose compilation depends both on
ANSI features and on compile time switches.

Here is a suggestion:

For "almost" ANSI compilers, I don't use __STDC__ to identify them;
instead, I have a set of defines in a universal include file (which
gets included before any of my include files) which I turn on for
various features available with the compiler. This include file might
look like:

#ifdef sun3                     /* standard SunOS compiler */
#define HAS_VOID
#define BROKEN_VOID
#define HAS_UCHAR
#define HAS_ULONG
...
#define SYS_DEFINED
#endif

#ifdef MSC                      /* Microsoft compiler */
#define ANSI_PREP
#define ANSI_PROTO
#define ANSI_INCLUDE
#define HAS_VOID
#define HAS_UCHAR
#define HAS_ULONG
...
#define SYS_DEFINED
#endif

...etc.

/* This SYS_DEFINED is a kludge; it is needed for those !@#$%
   compilers that define their own symbol and then go on to define
   __STDC__. Note that this is the only place __STDC__ gets
   referenced; if one wants an ANSI feature, one needs to have a
   define for it that gets set here. */

#ifndef SYS_DEFINED
#ifdef __STDC__
#define ANSI_PREP
#define ANSI_PROTO
#define ANSI_INCLUDE
#define HAS_VOID
#define HAS_UCHAR
#define HAS_ULONG
...
#endif
#endif
#undef SYS_DEFINED

Now then, we come to the question: what should an implementation do
if some compile time switch renders the compiler nonconforming?  One
solution is for the compiler to reverse the above: without the
switch, define __STDC__, with it, define a special symbol for the
compiler.

I think that is ugly; furthermore, it really doesn't deal with the
situation. Since I set the compiler switch, I ought to know what way
the switch changes the compiler's behavior; I should have arranged
that, when using the switch, the program compiles correctly.  In other
words, what I want is a compiler which is ANSI, but which has just
those changes represented by the compiler switch.  (And if I want the
compiler to not pretend to be ANSI, I can just -U__STDC__ or the
equivalent.)

I propose that __STDC__ == 0 be reserved (obviously only custom can
apply here) for use by compilers that are conforming when no compiler
switches are specified. Those compilers would set __STDC__ == 1 then.
When the user specifies any switch that makes the compiler non-
conforming, it sets __STDC__ to 0.

There are two advantages to the above. The first is that the
programmer gets a meaningful __STDC__, even when he has used a compile
time switch.  This is particularly useful when one is writing
conforming (but not strictly conforming) programs which are to be
portable between different environments.

The second is more subtle: by defining a meaning for __STDC__ == 0,
we have a standard by which we can judge the use of __STDC__;
pressure to comply with this "standard" may help get rid of those
compilers that use __STDC__ == 0 to mean that the compiler is
"almost" ANSI.

In summary:

	A compiler whose normal mode is not ANSI should not define
	__STDC__.

	A compiler whose normal mode is ANSI should define __STDC__
	== 1.

	A compiler whose normal mode is ANSI, but which is operating
	in a different mode, specified by compile switches or other
	means which require the user to turn them on, defines __STDC__
	== 0.

---
Bill
{ uunet!proxftl | novavax } !twwells!bill



More information about the Comp.std.c mailing list