[comp.std.c] Want the word on __STDC__

dfenyes@thesis1.hsch.utexas.edu (David Fenyes) (02/20/91)

Hello,

Here's the question:

Everybody knows that ANSI C compilers with ANSI preprocessors should
have __STDC__ #defined to 1, and K&R compilers with K&R cpp don't have
__STDC__ #defined at all.

The question is:  Does an ANSI cpp ALWAYS #define __STDC__, even if it
is used intentionally with a K&R compiler (#defined to 0)?
Mark Williams uses an ANSI cpp with their non-ANSI compiler, and
#defines __STDC__ to 0, which causes all sorts of problems when code
tests #ifdef __STDC__  . . . (rather than #if __STDC__).

Who is the offender? MWC, or those #ifdef'ers out there?

It makes sense to #define __STDC__ so the code can take advantage
of the ANSI cpp features, while still not using ANSI prototypes, etc.

If anyone knows the answer from the ANSI documents, please let me
know, or post to the net.  I'd be glad to summarize any info mailed
to me for the net.

Thanks,
David.
--
David Fenyes                                  dfenyes@thesis1.hsch.utexas.edu
University of Texas Medical School            Houston, Texas

gwyn@smoke.brl.mil (Doug Gwyn) (02/20/91)

In article <4755@lib.tmc.edu> dfenyes@thesis1.hsch.utexas.edu (David Fenyes) writes:
>The question is:  Does an ANSI cpp ALWAYS #define __STDC__, even if it
>is used intentionally with a K&R compiler (#defined to 0)?

It does whatever it does.

The C standard constrains only conforming implementations, which must
in effect predefine __STDC__ to 1.  Non-conforming implementations are
outside the scope of the standard.

Having said that, I would add that implementors who #define __STDC__
to anything at all in non-conforming variants of their compilers are
not doing anyone a favor, and I wish they would desist from that
practice.

henry@zoo.toronto.edu (Henry Spencer) (02/21/91)

In article <4755@lib.tmc.edu> dfenyes@thesis1.hsch.utexas.edu (David Fenyes) writes:
>The question is:  Does an ANSI cpp ALWAYS #define __STDC__, even if it
>is used intentionally with a K&R compiler (#defined to 0)?

An "ANSI cpp"?  There is no such thing; there are only ANSI C implementations.
ANSI C does not specify any aspect of the behavior that results if you use
part of an ANSI C implementation in conjunction with something else.  It does
not even promise that this is possible at all, since many C compilers do
not *have* a separate preprocessor.

>Mark Williams uses an ANSI cpp with their non-ANSI compiler, and
>#defines __STDC__ to 0, which causes all sorts of problems when code
>tests #ifdef __STDC__  . . . (rather than #if __STDC__).
>
>Who is the offender? MWC, or those #ifdef'ers out there?

MWC.  Defining __STDC__ to be anything in a non-ANSI environment is a dumb
thing to do.  There is no portable meaning for a __STDC__ value of 0.
-- 
"Read the OSI protocol specifications?  | Henry Spencer @ U of Toronto Zoology
I can't even *lift* them!"              |  henry@zoo.toronto.edu  utzoo!henry

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (02/22/91)

In <1991Feb20.175702.28682@zoo.toronto.edu> henry@zoo.toronto.edu
(Henry Spencer) writes:

     ...since many C compilers do not *have* a separate preprocessor.

I may have to eat my words, but after extensive searching, I haven't
yet found any commercially available C compiler that wasn't accompanied
by a separately invokable preprocessor.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

henry@zoo.toronto.edu (Henry Spencer) (02/22/91)

In article <2961@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>     ...since many C compilers do not *have* a separate preprocessor.
>
>I may have to eat my words, but after extensive searching, I haven't
>yet found any commercially available C compiler that wasn't accompanied
>by a separately invokable preprocessor.

Note that the two statements are not entirely inconsistent:  it is quite
possible to invoke only the preprocessor functionality of a compiler that
does not break it out as a separate program.  I assure you that there are
quite a few compilers that integrate the preprocessor into the scanner;
the Whitesmiths compiler was the first.  In fact, when implementing from
scratch, it makes little sense to separate preprocessor and scanner,
since it means tokenizing the source twice.

I suspect that most any sensible implementor would provide a way to invoke
the preprocessor functionality only.  However, there is no requirement to
do so, and no guarantee that an ANSI implementation will do so... which was
the point of my original posting.
-- 
"Read the OSI protocol specifications?  | Henry Spencer @ U of Toronto Zoology
I can't even *lift* them!"              |  henry@zoo.toronto.edu  utzoo!henry

steve@taumet.com (Stephen Clamage) (02/23/91)

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:

>In <1991Feb20.175702.28682@zoo.toronto.edu> henry@zoo.toronto.edu
>(Henry Spencer) writes:

>     ...since many C compilers do not *have* a separate preprocessor.

>I may have to eat my words, but after extensive searching, I haven't
>yet found any commercially available C compiler that wasn't accompanied
>by a separately invokable preprocessor.

Oregon C/C++ (from Oregon Software) is a single program which includes
integral preprocessing.  That is, input is preprocessed on the fly, and
there is no separate preprocessor output required.  There is no separate
preprocessor program.  However, you may ask for preprocessor output as
an option, so this may qualify as a "separately invokable preprocessor".
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

meissner@osf.org (Michael Meissner) (02/23/91)

In article <2961@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:

| In <1991Feb20.175702.28682@zoo.toronto.edu> henry@zoo.toronto.edu
| (Henry Spencer) writes:
| 
|      ...since many C compilers do not *have* a separate preprocessor.
| 
| I may have to eat my words, but after extensive searching, I haven't
| yet found any commercially available C compiler that wasn't accompanied
| by a separately invokable preprocessor.

The Data General AOS/VS C compiler (and the DG/UX MV/Eclipse C
compiler which was the same beast repackaged for unix) had the
preprocessor as part of the tokenizer.  This is from the horse's
mouth, since I wrote the compiler front end, and the preprocessor
never was a separate program.  It started shipping in the 1982 time
frame.

--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

Considering the flames and intolerance, shouldn't USENET be spelled ABUSENET?

barmar@think.com (Barry Margolin) (02/23/91)

In article <2961@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>I may have to eat my words, but after extensive searching, I haven't
>yet found any commercially available C compiler that wasn't accompanied
>by a separately invokable preprocessor.

As usual, the best place to look for an unusual C compiler is Symbolics.
Their preprocessor may be invokable separately, but it isn't documented and
I think it outputs tokens, not text.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

blarson@blars (02/23/91)

In article <2961@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>I may have to eat my words, but after extensive searching, I haven't
>yet found any commercially available C compiler that wasn't accompanied
>by a separately invokable preprocessor.

Prime C for their 50 series.

The output of Microware's os9/68k C compiler cpp is not legal C, and
cannot be used with other C compilers.

-- 
blarson@usc.edu
		C news and rn for os9/68k!
-- 
Bob Larson (blars)	blarson@usc.edu			usc!blarson
	Hiding differences does not make them go away.
	Accepting differences makes them unimportant.

peter@ficc.ferranti.com (Peter da Silva) (02/26/91)

I first ran into a C compiler with no separate preprocessor and no way of
running just the preprocessor in 1981. The compiler was the BDS compiler for
CP/M.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

rfg@NCD.COM (Ron Guilmette) (03/03/91)

In article <15260@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>
>Having said that, I would add that implementors who #define __STDC__
>to anything at all in non-conforming variants of their compilers are
>not doing anyone a favor, and I wish they would desist from that
>practice.

I assume that you also get irrate about implementors who define __STDC__
to something other than 1.

AT&T's CI5 C compiler (for SVR4) can do any one of the following three
possible things (depending upon the options used):

	leave __STDC__ undefined
	predefine __STDC__ to 0
	predefine __STDC__ to 1

The corresponding three "compilation modes" are (respectively):

	compile using both K&R and ANSI rules but use K&R rules in
	cases where there are conflicts

	compile using both K&R and ANSI rules but use ANSI rules in
	cases where there are conflicts

	compile using only ANSI rules (but with some standard comforming
	extensions)

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// New motto:  If it ain't broke, try using a bigger hammer.

gwyn@smoke.brl.mil (Doug Gwyn) (03/05/91)

In article <4203@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>I assume that you also get irrate about implementors who define __STDC__
>to something other than 1.

I have no problem with an otherwise CONFORMING implementation defining
__STDC__ to something other than 1, although why would it?  At least
that does not cause problems for strictly conforming applications.

>The corresponding three "compilation modes" are (respectively):

But that is NOT what __STDC__ means according to the C standard,
which is why there is a problem with people trying to use it for
other purposes.

fred@mindcraft.com (Fred Zlotnick) (03/07/91)

In article <15381@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <4203@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>>I assume that you also get irrate about implementors who define __STDC__
>>to something other than 1.
>
>I have no problem with an otherwise CONFORMING implementation defining
>__STDC__ to something other than 1, although why would it?  At least
>that does not cause problems for strictly conforming applications.

But it CAN cause problems (in addition to which, such an implementation
is no longer conforming according to section 3.8.8): since we know that
nonconforming implementations do in fact sometimes define __STDC__ to
something other than 1, it would be useful to protect your code by using
the test

  #if __STDC__ == 1

rather than

  #ifdef __STDC__

This works if __STDC__ is not defined, since (according to 3.8.1) it is
"replaced with the pp-number 0".  But it won't give the desired result if
an "otherwise CONFORMING implementation" has __STDC__ defined to a value
not 1.

You could argue that nonconforming implementations are free to do whatever
they like, including defining __STDC__ to be 1.  But this would be nasty,
and in practice no intentionally nonconforming implementation is likely to
do it.
Fred Zlotnick                       |	#include <std.disclaimer>
fred@mindcraft.com                  |	#include <brilliant.quote>
...!{decwrl,ames,hpda}!mindcrf!fred |

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (03/07/91)

In <668288453.3046@mindcraft.com> fred@mindcraft.com (Fred Zlotnick) 
recommends the test

>  #if __STDC__ == 1

to detect nonconforming implementations.  Unfortunately there are
two problems with this.

First, it is quite possible that a future ANSI C standard will bump up
the value of __STDC__ to 2, thus breaking code that assumes that
(__STDC__ != 1) implies (not standard C).

Second, some existing nonconforming implementations of C will
fail to compile expressions like

   #if something == something.

Now you may say these implementations aren't C, and you might be right,
but they are *called* C by many users, and they will be upset that
ostensibly portable C code won't compile.  Truly defensive programmers
assume that the preprocessor does not understand C expressions.  Such
flaky implementations are fortunately dying out, but I could easily
ruffle through my old disks and find a few that aren't quite dead yet.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

em@dce.ie (Eamonn McManus) (03/08/91)

fred@mindcraft.com (Fred Zlotnick) writes:
>... since we know that
>nonconforming implementations do in fact sometimes define __STDC__ to
>something other than 1, it would be useful to protect your code by using
>the test
>  #if __STDC__ == 1
>rather than
>  #ifdef __STDC__

There are problems with that, though, quite apart from otherwise
conforming hypothetical implementations that define __STDC__ to be other
than 1.  The replacement of undefined identifiers by 0 may have been a de
facto Unix standard but it was nowhere mentioned in K&R1 so it would have
been reasonable for a pre-standard implementation to make it an error for
a #if to contain an undefined identifier.

If I want my code to run on pre-standard implementations (which presumably
I do if I care about __STDC__) then I am reluctant to depend on
  #if __STDC__
or
  #if __STDC__ == 1
rather than
  #ifdef __STDC__
which would have been safe had it not been for cretinous implementors who
made half-standard implementations with __STDC__ defined but 0.

,
Eamonn

rbutterw@watmath.waterloo.edu (Ray Butterworth) (03/08/91)

In article <2986@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>First, it is quite possible that a future ANSI C standard will bump up
>the value of __STDC__ to 2, thus breaking code that assumes that
>(__STDC__ != 1) implies (not standard C).

The failure to fully define __STDC__ was obviously a mistake,
and some vendors have thoroughly abused it.

Perhaps the next version of the standard could denegrate __STDC__
and introduce a new definition, say something like
   #define __ANSI_X3_159__ 1989
and explicitly say that
   #if defined(__ANSI_X3_159__)
is the recommended test for an ANSI Standard compiler.
One could also use tests such as
   #if __ANSI_X3_159__ < 2001
   #if __ANSI_X3_159__ == 1989
to check for the version of the Standard.
They should also state that if the symbol is defined with any
value other than those explicitly listed in the standard,
the compiler must generate a fatal error, rather than leaving
the behaviour as undefined as it is now with __STDC__.

If they really like the __STDC__ name though, they could
always say the same as above, but with (__STDC__ == 1)
having the same meaning as (__STDC__ = 1989), but using a
new symbol would probably avoid confusion.

steve@taumet.com (Stephen Clamage) (03/09/91)

rbutterw@watmath.waterloo.edu (Ray Butterworth) writes:

>In article <2986@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>>First, it is quite possible that a future ANSI C standard will bump up
>>the value of __STDC__ to 2, thus breaking code that assumes that
>>(__STDC__ != 1) implies (not standard C).

>The failure to fully define __STDC__ was obviously a mistake,
>and some vendors have thoroughly abused it.

Wait a minute!  My copy of X3.159-1989 says __STDC__ is defined as
"the decimal constant 1".  That seems about as clear and fully-defined
as it could be.  A processor which defines it to be some other value is
not in compliance with the Standard.  The purpose of a standard is act as
a contract between the compiler writer and the compiler user; if the user
writes a conforming program, the compiler will behave in a predictable way.
A processor might intend not to be in compliance with the standard, in
which case all bets are off.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

gwyn@smoke.brl.mil (Doug Gwyn) (03/11/91)

In article <668288453.3046@mindcraft.com> fred@mindcraft.com (Fred Zlotnick) writes:
>>I have no problem with an otherwise CONFORMING implementation defining
>>__STDC__ to something other than 1, although why would it?  At least
>>that does not cause problems for strictly conforming applications.
>But it CAN cause problems (in addition to which, such an implementation
>is no longer conforming according to section 3.8.8): since we know that
>nonconforming implementations do in fact sometimes define __STDC__ to
>something other than 1, it would be useful to protect your code by using
>the test
>  #if __STDC__ == 1
>rather than
>  #ifdef __STDC__

The problem is that __STDC__ is likely to be set to 2 for an implementation
that conforms to an upward-compatible future revision of the C standard, so
#ifdef __STDC__ is the nicest way for current strictly-conforming programs
to accommodate both X3.159-1989 conforming implementations and our best
estimate of X3.159-199x conforming implementations.

Unfortunately, use of #if some_func(__STDC__) implies that the program is
trying to determine whether or not to use some system-specific substitute
code for features that may not exist in non-conforming implementations.
I believe the intention of X3J11 was that __STDC__ would be useful for
this purpose, but some C vendors have spoiled that by "helpfully" defining
__STDC__ in their non-conforming implementations.  In fact I have seen
__STDC__ defined as 1 in some non-conforming implementations.

The practical effect is that you have the non-conforming vendors to thank
for making __STDC__ useless in portable code.  Instead, you must somehow
devise your own solution to this environment testability issue.  What we
have done locally is for our universal configuration header <std.h> to
define a macro STD_C as either 0 or 1, 0 meaning not a conforming
implementation and 1 meaning conforming to X3.159-1989.  (Other values
reserved for possible future revisions of the standard.)  One of the first
steps in porting software is to edit <std.h> to correctly set STD_C as
well as some other system-dependent standard macros etc.

gwyn@smoke.brl.mil (Doug Gwyn) (03/11/91)

In article <1991Mar7.194733.18150@watmath.waterloo.edu> rbutterw@watmath.waterloo.edu (Ray Butterworth) writes:
>The failure to fully define __STDC__ was obviously a mistake,
>and some vendors have thoroughly abused it.
>Perhaps the next version of the standard could denegrate __STDC__
>and introduce a new definition, say something like
>   #define __ANSI_X3_159__ 1989

The real problem is that the standard can constrain only the behavior
of CONFORMING implementations; nonconforming implementations can do
whatever they please, including pretending to be standard conformant.

Your suggestions did not address this fundamental problem any better
than the existing specification for __STDC__ did.  I am of the opinion
that there is no method by which any standard could solve the problem.

wirzenius@cc.helsinki.fi (Lars Wirzenius) (03/12/91)

In article <lampblack@dce.ie>, em@dce.ie (Eamonn McManus) writes:
> If I want my code to run on pre-standard implementations (which presumably
> I do if I care about __STDC__) then I am reluctant to depend on
>   #if __STDC__
> or
>   #if __STDC__ == 1
> rather than
>   #ifdef __STDC__
> which would have been safe had it not been for cretinous implementors who
> made half-standard implementations with __STDC__ defined but 0.

How about:

#ifndef STD_C
#    ifdef __STDC__
#        if __STDC__ == 1
#            define STD_C
#        endif
#    endif
#endif

and then code the rest of the program depending on STD_C instead of
__STDC__? 

Incidentally, I would think that it would be better (or at least more
useful) to use constants that describe characteristics of the system,
rather than conformance to the standard.  For example, I think
prototypes are available in several non-standard (or almost standard)
implementations, which don't do the Right Thing for __STDC__.  Another
example is header files.  The standard introduces <limits.h> (doesn't
it?), which may or may not be available in non-standard implementations. 
It might be a local enchancement to make standard conforming programs to
compile a teeny bit easier, but might not be available on other sites
with the same C implementation. 

-- 
Lars Wirzenius    wirzenius@cc.helsinki.fi

rbutterw@watmath.waterloo.edu (Ray Butterworth) (03/12/91)

In article <622@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>rbutterw@watmath.waterloo.edu (Ray Butterworth) writes:
>>The failure to fully define __STDC__ was obviously a mistake,
>>and some vendors have thoroughly abused it.
>Wait a minute!  My copy of X3.159-1989 says __STDC__ is defined as
>"the decimal constant 1".  That seems about as clear and fully-defined
>as it could be.

By "fully define" I meant that it should mention its intended use
and explicitly forbid other uses.

>From: gwyn@smoke.brl.mil (Doug Gwyn)
>In article <1991Mar7.194733.18150@watmath.waterloo.edu> rbutterw@watmath.waterloo.edu (Ray Butterworth) writes:
>>Perhaps the next version of the standard could denegrate __STDC__
>>and introduce a new definition, say something like
>>   #define __ANSI_X3_159__ 1989
>The real problem is that the standard can constrain only the behavior
>of CONFORMING implementations; nonconforming implementations can do
>whatever they please, including pretending to be standard conformant.

If instead of simply saying that __STDC__ will be 1, the Standard had
explicitly said something like __STDC__ will be 1 for X3.159-1989,
will have other values for later versions of the standard, and all
values of this macro are reserved by the Standard, things would have
been better.  Sure, it could still be abused, but there would be
less justification for the abuse.  Simply saying that it is 1 made
it very easy for some people to interpret this as meaning that
one should define it as something else to indicate non conformance.

>Your suggestions did not address this fundamental problem any better
>than the existing specification for __STDC__ did.  I am of the opinion
>that there is no method by which any standard could solve the problem.

Certainly there is no guaranteed solution, but one can make things
more difficult to abuse.  The name ANSI_X3_159 sort of indicates
that the name belongs to ANSI Standard C.  The current (presumptuous)
name could (and is) easily claimed by anyone else that wants to
declare their version as "standard" (and not necessarily your standard).