From: jfw@ksr.com (John F. Woods)
Newsgroups: comp.std.c
Subject: Re: Compatability of enum types and integer types
Date: 22 Dec 92 16:52:28 EST

diamond@jit533.jit.dec.com (Norman Diamond) writes:
>In article <1992Dec21.225604.18749@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>>The ANSI C standard says (in 3.5.2.2):
>>	"Each enumerated type shall be compatible with an integer type;
>>	the choice of type is implementation-defined."
>>I interpret it to mean that there *must* exist some integer type `T' such that
>>		enum E { red, green, blue } object;
>>		enum E object;
>>		T object;
>>... is a valid translation unit.
>>The person on the other side of this discussion seems to be claiming that
>>[...] the implementation may "put the fix in" so that no matter what type
>>you try to use for `T', the implementation will say "Sorry.  You guessed wrong
>Being implementation-defined means that it must be documented.  Regarding
>some other implementation-defined matters (e.g. which of two possible results
>is obtained from the % operator) most of the regulars in this newsgroup seem
>to feel that the implementation must define a result that is identical over
>all usages.  This kind of opinion suggests that the documentation must tell
>you which type you can use for `T'.
>My opinion is that the documentation can tell you that the implementation
>plays dirty pool.  However, I seem to be a minority of 1.

I think you're a minority of two.  I can't see any way for a program to make
use of this in a way that exposes the type yet is guaranteed.  I think one
can argue that

	enum thing { small, big=INT_MAX };

is required to be compatible with a type no shorter than int, but that still
leaves long (and, actually, if all the integral types are the same size, it
could *still* be compatible only with char).  I think a definition of

	Enumeration types are compatible with "int", unless an object in
	a translation unit is declared as an enumeration type and as an
	"int" in the same translation unit or a different translation unit
	at link time, in which case enumeration types are compatible with
	"long".

meets all the requirements present in the standard.  (There are certainly other
instances of "implementation-defined behavior" where there is no particular
requirement that the behavior be useful or desirable).  I think it's pretty
clear that the type compatibility of enumerations need *not* be identical
over all usages:

	enum boolean { true, false };	/* can be compatible with char */
	enum wider { base, figure = 257 };/* can't be compatible with
					   * 8-bit char but can be short */
	enum widest { small, big = INT_MAX }; /* must be an int, except when
						 "shorter" types are the same
						  size as int */
	enum oops { small, wrong = LONG_MAX }; /* violates a constraint unless
						  int and long are the same
						  size */						
It might be argued, however, that since the Standard could merely have said
that enumerations are integral types, but are not *compatible* with any
integral types, that there is an implicit requirement that one be able to
take advantage of that type compatibility.  The Rationale, alas, sheds no
light on the matter.  I think the compatibility requirement only buys one
the ability to pass enumerations to functions expecting integral types with
some hope of portability (though I suspect that if enumerations can be
unsigned types, it opens an even larger can of worms).