Can you approximate subranges in C?

P

Paul Eggert

CBFalconer said:
It would be fairly easy to graft such a construct with:

enum subrangetype {MINVAL .. MAXVAL};

where MINVAL and MAXVAL are constant integral values.

Suppose you need an integer type "foo" that can represent MINVAL,
MAXVAL, and all values in between. Will the following type do?

typedef enum { foo_lo = MINVAL, foo_hi = MAXVAL } foo;
 
C

Chris Torek

Suppose you need an integer type "foo" that can represent MINVAL,
MAXVAL, and all values in between. Will the following type do?

typedef enum { foo_lo = MINVAL, foo_hi = MAXVAL } foo;

This might be fixed in C99 (and no doubt someone will post about
it if so), but in C89, at least, it is not guaranteed to work.
A hypothetical "evil" implementation might make the enumerated
type "foo" compatible with, e.g., unsigned char and thus give it
a maximum integral range of [0..255], even if MINVAL is -32767
and MAXVAL is 32767.

I doubt there are any compilers that do this, but I would be not
terribly surprised to find 16-bit-"int" compilers that make enum foo
compatible with plain (signed) int even when MINVAL is -2147483647
and MAXVAL is 2147483647, which is guaranteed to fit within plain
mlong.
 
M

Micah Cowan

Chris Torek said:
This might be fixed in C99 (and no doubt someone will post about
it if so)

It has been fixed, in that the type chosen must be capable of
representing all enumerated types; however, the constraint still
exists that all of the constant expressions enumerated must be
representable as an int, which means an implementation could find its
work easiest by simply always using an int, and warning (at least) if
an expression falls outside of that.

In any case (to OP), C isn't Ada; you wouldn't have the advantage of
being able to *constrain* the value to that range (if that's what you
wanted). At any rate, you're at least as well off employing int as
enum.

HTH,
-Micah
 
J

Jun Woong

Chris Torek said:
This might be fixed in C99 (and no doubt someone will post about
it if so), but in C89, at least, it is not guaranteed to work.

Could you elaborate on what difference exactly you refer to here?
As I recall, there is only wording improvement between those
standards, C90+TCs and C99.
 
J

Jun Woong

Micah Cowan said:
From what I could read, C90 states only that enum be compatible with
an integer type; which specific type is implementation-defined. There
doesn't seem to be a requirement that it choose a type capable of
representing all enumerated values (which would still be a poor QoI,
of course, but still...). This was fixed in C99.

From the TC2 for C90:

In subclause 6.5.2.2, page 61, second paragraph of Semantics,
change:

Each enumerated type shall be compatible with an integer type;
the choice of type is implementation-defined.

to:

Each enumerated type shall be compatible with an integer type.
The choice of type is implementation-defined, but shall be capable
of representing the values of all the members of the enumeration.
 
M

Mr. 4X

Paul Eggert said:
Suppose you need an integer type "foo" that can represent MINVAL,
MAXVAL, and all values in between. Will the following type do?

typedef enum { foo_lo = MINVAL, foo_hi = MAXVAL } foo;

I don't think this makes much sense without Pascal style BUILT IN RANGE
CHECKING. Pascal has (optional) RANGE CHECKING for variables, which IIRC
incvludes range check for SUBRANGES.
 
J

Jun Woong

Paul Eggert said:
As an aside, the wording in C99 does not seem to specifically rule out
the following declaration:

enum { foo = INT_MAX, foo_plus_one };

though clearly this violates the intent of the standard, as
'foo_plus_one' is of type 'int'. Certainly no diagnostic is required
for this bogus declaration, though I think one ought to be.

I think that the intent is to still apply the constaint in the
subclause and require a diagnostic:

Each subsequent enumerator with no = defines its enumeration
constant as the value of the constant expression obtained by
~~~~~~~~~~~~~~~~~~~~~~~
adding 1 to the value of the previous enumeration constant.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

But, if you disagree, how about:

6.6p3 (constraints)

Each constant expression shall evaluate to a constant that is in
the range of representable values for its type.

?
 
P

Paul Eggert

I think that the intent is to still apply the constaint in the
subclause and require a diagnostic:

Each subsequent enumerator with no = defines its enumeration
constant as the value of the constant expression obtained by
~~~~~~~~~~~~~~~~~~~~~~~
adding 1 to the value of the previous enumeration constant.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

OK, I guess I can buy that, though it's a little indirect for my taste.
 
C

Clive D. W. Feather

Paul Eggert said:
As an aside, the wording in C99 does not seem to specifically rule out
the following declaration:

enum { foo = INT_MAX, foo_plus_one };

The intent was that this wording:

Each subsequent enumerator
with no = defines its enumeration constant as the value of
the constant expression obtained by adding 1 to the value of
the previous enumeration constant.

generates a constant expression (in this case, "foo + 1") to which the
constraint applies. I think there was a C90 DR on the topic.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top