POSIX, ANSI C, and __STDC__

D.F.Prosser dfp at sfmin.UUCP
Sat Jan 21 06:38:33 AEST 1989


Until now I've been able to keep from adding my own pronouncements
to netnews, but the continuing discussion about __STDC__ and various
related issues, and in particular, statements (both accurate and
inaccurate) about AT&T's future C compilation system have convinced
me that I, too, need to speak my piece.

Doug Gwyn (in <9422 at smoke.BRL.MIL>) characterizes four compilation
system variations:
  1. cc  - behaves just like the last UNIX C compiler (UNIX, of course,
	   is a registered trademark of AT&T).
  2. acc - ANSI C conforming (allowing valid extensions).
  3. pcc - both POSIX and ANSI C conforming (in which an application
	   must have _POSIX_SOURCE #defined in order to get any
	   additional identifiers).
  4. fcc - POSIX conforming and ANSI C nonconforming only due to name
	   space additions disallowed by ANSI C.

AT&T's ANSI C-based compilation system has three versions, all
available through the cc command's new -X compilation mode option:
  cc -Xt ("transition", the default mode)
	All compatible ANSI C changes are available.  This includes
	function prototypes, void*, and the new keywords.  It is the
	intent of this mode that all code that used to compile (without
	warnings) will compile (possibly with warnings) except for
	clashes with the new keywords: const, signed, volatile.

	In those few places where ANSI C requires different semantics
	(what the ANSI C Rationale calls QUIET CHANGES), a warning will
	be issued, but the old semantics will be used.  The big example
	is value- vs. unsigned-preserving promotion rules.  All of these
	warnings are easily eliminated by writing "unambiguous code".

  cc -Xa ("ansi", eventual default mode)
	Same as -Xt except that ANSI C semantics will be used in the
	QUIET CHANGE situations.

  cc -Xc ("conforming", not intended ever to be the default mode)
	Same as -Xa except the name space is reduced to ANSI C conformance
	and all still missing, ANSI C required diagnostics are enabled.
	In order to gain access to POSIX's extra declarations, the
	_POSIX_SOURCE macro must be #defined by the application code.

(These modes can be modified by use the -v option which enables the extra
diagnostics required by ANSI C, as well as some lint-like warnings all
of which can be silenced through use of "reasonable" code--not through
use of lint comments or #pragmas.  I believe that a compiler's job is to
do its best to translate the code you gave it; it's lint's job to check
for portability problems, and so on.)

Since both AT&T and our customers want to know whether the new ANSI C
features are available during compilation, there needed to be some always
available macro name to check.  Moreover, the ANSI C standard headers need
to know whether to include names beyond those allowed by ANSI C.  However,
there was no need to distinguish between the first two modes.  We could
have made up some macro like __ANSI__ or the like, but any use of such
a name would render the application nonportable (its behavior would be
undefined with other compilation systems).  We could have made up a name
like ANSI_C that would be #defined only in -Xt and -Xa and #undef'd in
-Xc, but then the #if[def] checks would get even more complicated.  Thus,
the (obvious) solution was to always pre-#define __STDC__, but have its
value be 0 for -Xt and -Xa.  It would be 1 only when conforming: -Xc.

I still believe in this argument.  It serves both our customers and AT&T
best, it doesn't "lie" about conformance, and it follows the spirit of
the Standard.

However, Doug believes--I am guessing here as I have yet to receive the
email to which he alluded regarding this point--that application code
cannot make use of __STDC__ == 0 in any(?) way.  I note that Doug then
said (in article <9445 at smoke.BRL.MIL>) that a "gentleman's agreement"
about what __STDC__ == 0 means would allow such use.  I completely agree.
This is, in fact, what I hope AT&T's __STDC__ == 0 feature will serve as
a basis for.

I would propose that __STDC__ be #defined to be 0 in C compilation systems
that meet all ANSI C conformance requires except for:
  1. the inclusion of nonconforming "common extensions" listed in A.6.5,
  2. not issuing otherwise required diagnostics when language extensions
     are used, and/or
  3. extra names declared or defined in standard headers.
If __STDC__ is 1, the compilation system must be conforming.

This seems to me to characterize the C compilation systems vendors will
have to provide to satisfy existing customers.  I don't care whether this
is the default version, or whether such a version is even available.  If
there weren't existing implementations or other standards that have
"fiddled" with the name space in the standard headers, I'd be pushing for
only conforming ANSI C use of __STDC__, but it is simply not practical.

It is worth noting that many C compilation systems will probably have
__STDC__ #defined to be 1 and will actually be nonconforming.  I would
like to believe that the nonconforming behavior is an oversight or a bug
and that the vendor will endeavor to correct the situation.  An agreement
such as the above will allow give vendors breathing room between the
strict letter of the ANSI C law, and their customers' needs.

Doug proposes (in article <9436 at smoke.BRL.MIL>) that by default the UNIX
cc command should provide a pre-#defined _POSIX_SOURCE and also have
__STDC__ #defined to 1.  This would be "a lie" as I understand the ANSI C
standard (and most people figure I know it pretty well :-) since a strictly
ANSI C conforming program could end up with extra names.  His alternative
of needing a -D_POSIX_SOURCE to the cc command invocation *exactly* matches
AT&T's by invoking ``cc -Xc -D_POSIX_SOURCE''.  (Although I'd probably
recommend setting CC to this instead of CFLAGS.)


Speaking as an X3J11 member, I too (just like Doug) was disappointed with
POSIX's mutation of the proposed macro to solve the name space issue.  It
was informally agreed (over the phone) that POSIX would describe some macro
whose definition would allow an implementation to add POSIX's extra names
to the ANSI C and POSIX shared header files.  The macro could even be one
that was #defined by the system in a non-ANSI C header file, such as
<unistd.h>, so merely #including such before any shared header file would
have sufficed.  It was unfortunate that POSIX produced the inverted
version of this idea.


As a related issue, the cc command's -D and -U options do not render a
compilation system nonconforming.  They are taken to be the equivalent
series of #defines followed by a series of #undefs inserted just before
the first line of the named source file(s).  They are explicitly provided
by the application writer, and as such are not actually predefined macros.

On another point, it was stated that __STDC__ cannot be undefined or
its value be changed.  This is not true.  The behavior of a program that
attempts such operations is undefined.  (See section 3.8.8.)  No diagnostic
is required nor is an implementation constrained to ignore the request.

Finally, I believe that X3J11's decision not to describe "levels" of
conformance was appropriate and the best choice--other language standards
with such have all had problems in this regard.

Dave Prosser, AT&T X3J11 Principal, X3J11 Redactor
AT&T Bell Labs, SF1-348, (201)522-6227, dfp at attunix.att.com



More information about the Comp.std.c mailing list