__STDC__ and non-conforming ANSI C compilers

Doug Gwyn gwyn at smoke.BRL.MIL
Fri Jan 20 07:31:43 AEST 1989


In article <12570003 at hpclsue.HP.COM> sue at hpclsue.HP.COM (Sue Meloy) writes:
>But, for syntax extensions and name space pollution, I do feel that it
>may be reasonable to define __STDC__.  In particular, POSIX requires
>additional names that would pollute a strict ANSI name space.  Is it
>reasonable to say that __STDC__ should not be defined in a POSIX
>implementation?

Hi, Sue!

That's a tough question, because the intention was for an
implementation to readily be simultaneously ANSI C conforming
and POSIX conforming. Unfortunately, as I discussed here recently,
it wasn't specified quite right, so simultaneous conformance,
while technically possible, isn't very helpful (since it forces
applications to have to do something special to get at some of
the POSIX names).

Because of this intention, it would be reasonable to have __STDC__
defined as 1 in a POSIX implementation that conformed to ANSI C in
every way except for the additional (constrained) names required
by POSIX also being visible upon including the standard headers.
My current opinion is that in such a case the implementation should
probably also predefine _POSIX_SOURCE, but counterarguments can
be made to that.  (For example, if an application DOES define this
symbol itself (as indicated by 1003.1), differently from the
implementation, the compiler would squawk.)

A very practical question for implementors is whether a C Standard
validation test can "gig" them for providing the POSIX extensions
in the standard headers.  I think the answer to that is very clear:
Yes, it can and should.  Therefore there needs to be some way to
invoke the compiler in both a "pure ANSI (plus allowed extensions)"
mode and an "almost ANSI but with POSIX extensions as well" mode.

People porting code to such an environment should be advised that
the default POSIX mode of invoking the compiler is not ANSI C
conformant, but only because of the additional identifiers in the
standard headers required by 1003.1, and that if they really need
guaranteed C Standard conformance, they need to invoke the other
flavor of the compiler.

I don't think that defining __STDC__ as 0 is helpful, unless there
is some "gentleman's agreement" about what that means (which seems
unlikely).

>As for syntax extensions (accepted silently), no strictly-conforming 
>program should be affected.  Programs that use the extension would not 
>receive a diagnostic, rendering the implementation non-standard, so 
>theoretically __STDC__ should not be defined.

Yes, where the C Standard requires a diagnostic, failure to produce
one renders the implementation non-conforming.  (Section 2.1.1.3.)

>Would defining __STDC__ in either of these situations cause problems?

To me as an application developer, the important use of __STDC__ is
to conditionalize source code so that one branch of the condition
has a guaranteed environment available (namely, that specified in
the Standard).  The other branch is just as bad as it always was.

There are extensions which are "transparent", since as you say no
strictly-conforming code (which is what one would put into the __STDC__
"true" branch) could be affected by them.  For example, adding a __near
type qualifier would be such an extension.  I see no reason to consider
such an implementation as PRACTICALLY non-conforming, so __STDC__
should be 1 if all extensions fall into this category, even though the
implementation is not TECHNICALLY a conforming one.  So far as any
reasonable use of __STDC__ goes, it is IN EFFECT a Standard-conforming
implementation, so "lying" about it with __STDC__ in this case can do
no practical harm.

>If not, is it OK to define it to 1, or should it be 0?

__STDC__==0 tells me NOTHING.  __STDC__==1 tells me that insofar as
strictly-conforming code goes, the implementation will "accept" it
(i.e. successfully translate and execute it).  That is what I need
to know.

>Doug, you mentioned that one implementation "guessed wrong" about
>your intent for using __STDC__.

The assumption was that the __STDC__ tester would care about such
things as prototypes and variadic-function support, but not about
extra names usurped by the implementation from the application's
name space.  I actually want to ensure that the name space is not
polluted, so I can do things like
	#include <stdio.h>
	#if __STDC__ /* whatever */
	/* "fdopen" is my natural name for the quantity
	   and what I would like to see when I'm debugging */
	FONTDESC *fdopen(const char *fontname);
	/* This function is MINE!  I want to call it "fdopen". */
	#else
	/* Just in case we're dealing with UNIX/POSIX etc.: */
	#define	fdopen	my_fdopen	/* best of a bad situation */
	FONTDESC *fdopen(/*const char *fontname*/);
	/* But I'll settle for "my_fdopen" if pressed. */
	#endif
	...
	{	FONTDESC *fd = fdopen("Courier");
	...
	}
Note that if the __STDC__ test results in "true" in a UNIX/POSIX
environment, this code will fail to compile.  It would have been
even worse if it had had conformable type to the function declared
in <stdio.h> but radically different semantics!

If there seems to evolve a general agreement that POSIX implementations
are going to define __STDC__ as 1 even though there are a handful of
extra names defined in the headers, then I'll simply avoid using those
names even though they may be what I wanted to use myself.  At least I
know what those extra names ARE.  I don't think we want to extend that
to OTHER such implementation extensions in standard headers, though,
because then I would not know what to expect when I include a standard
header and would have to give up entirely on the "clean name space"
guarantee that I find so valuable.  IEEE Std 1003.1 may deserve an
exception simply because it had attempted liaison with X3J11 on this
(even though it was botched).



More information about the Comp.std.c mailing list