enum safety

'Although variables of enum types may be declared, compilers need not
check that what you store in such a variable is a valid value for the
enumeration'

gcc produces an error for the code below as I'm trying to assign a
pointer to char to the a variable of type colour. Is gcc going beyond
the call of duty? Why would the standard allow compilers to accept
such code?

The compiler needn't check for a valid value. It must check for a
valid type. In this case, c is of type char*, purple is of type enum
colours, and there's no implicit conversion. This really has nothing
to do with it being an enum type.

This is perfectly legal; a particularly picky compiler might warn
about it, but it must accept it and it must produce the output
purple = 15

An enum type declaration really does two things. It creates an
enumerated type (which must be compatible with some existing integer
type and must be able to hold all the specified values), and it
creates a series of constants (which, oddly enough, are of type int,
not of the enumerated type). It looks a lot like the enumerated types
you might see in other languages such as Pascal, and you can use it
for the same purposes if you're careful, but it's really quite
different.

Note that this provides a cute mechanism for creating a named constant
of type int:

enum { MAX=1000 };

The type is anonymous and is never used; MAX is a constant of type int
with the value 1000. This is arguably cleaner than a macro, but it
doesn't extend to types other than int.

--
Keith Thompson (The_Other_Keith) <>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ian Collins wrote:
> Sard wrote:
>> Hi,
>>
>> Page 39 K&R2 says
>>
>> 'Although variables of enum types may be declared, compilers need not
>> check that what you store in such a variable is a valid value for the
>> enumeration'
>>
> This is why (in my opinion) enums are horribly broken in C.
Not necessarily. For example, you can have an object which can contain
a number up to 10 as numbers, and 11, 12 and 13 with special meanings. E.g.
enum rank { ACE = 1, JACK = 11, QUEEN = 12, KING = 13 };
enum rank foo = 7;
(For example mbrtowc can return a number of bytes, or 0, (size_t)(-2) and
(size_t)(-1) with special meanings. Here an enum won't do it because
constants must fit in an int, but one might have an int-returning function
with similar semantics. Maybe using negative numbers:
enum err_code { OUT_OF_MEMORY = -2, IO_ERROR = -1, MAX = INT_MAX };

Ian Collins <> writes:
> Army1987 wrote:
>> Ian Collins wrote:
>>> Sard wrote:
>>>> Page 39 K&R2 says
>>>>
>>>> 'Although variables of enum types may be declared, compilers need not
>>>> check that what you store in such a variable is a valid value for the
>>>> enumeration'
>>>>
>>> This is why (in my opinion) enums are horribly broken in C.
>> Not necessarily. For example, you can have an object which can contain
>> a number up to 10 as numbers, and 11, 12 and 13 with special meanings. E.g.
>> enum rank { ACE = 1, JACK = 11, QUEEN = 12, KING = 13 };
>> enum rank foo = 7;
>
> That illustrates the problem perfectly, you declare declare a valid
> range of values for rank and then legally assign some other arbitrary
> value to it. Useless.

It seems perfectly useful to me. An object of type enum range can
sensibly hold any value from 1 to 13. The values 1, 11, 12, and 13
happen to have names associated with them; the others are merely
numbers. The language guarantees that this will work (in fact, it
guarantees that values in the range 0..127 are valid).

A C enumerated type doesn't act like an enumerated type in, say,
Pascal or Ada, but it's not supposed to. It merely provides a set of
names for specific values, and an integral type that can hold all
those values.

--
Keith Thompson (The_Other_Keith) <>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Not really, using an enum here is useless. In fact, in some coding standard
(misra I think) its forbidden to use enums in this way. I dont want to argue
about that ruke, but it does show there are other ways in C to accomplish
this and not by abusing enum

Missing an identifier here ...
>> Aribitrary value assigned. Still useful.
>
> Not really, using an enum here is useless. In fact, in some coding
> standard (misra I think) its forbidden to use enums in this way. I dont
> want to argue about that ruke, but it does show there are other ways in
> C to accomplish this and not by abusing enum

Keith Thompson wrote:
> Ian Collins <> writes:
>> Army1987 wrote:
>>> Ian Collins wrote:
>>>> Sard wrote:
>>>>> Page 39 K&R2 says
>>>>>
>>>>> 'Although variables of enum types may be declared, compilers need not
>>>>> check that what you store in such a variable is a valid value for the
>>>>> enumeration'
>>>>>
>>>> This is why (in my opinion) enums are horribly broken in C.
>>> Not necessarily. For example, you can have an object which can contain
>>> a number up to 10 as numbers, and 11, 12 and 13 with special meanings. E.g.
>>> enum rank { ACE = 1, JACK = 11, QUEEN = 12, KING = 13 };
>>> enum rank foo = 7;
>> That illustrates the problem perfectly, you declare declare a valid
>> range of values for rank and then legally assign some other arbitrary
>> value to it. Useless.
>
> It seems perfectly useful to me. An object of type enum range can
> sensibly hold any value from 1 to 13. The values 1, 11, 12, and 13
> happen to have names associated with them; the others are merely
> numbers. The language guarantees that this will work (in fact, it
> guarantees that values in the range 0..127 are valid).
>
> A C enumerated type doesn't act like an enumerated type in, say,
> Pascal or Ada, but it's not supposed to. It merely provides a set of
> names for specific values, and an integral type that can hold all
> those values.
>
Or in C++, where they are first class types. A C enum is little
different from a typedef and a set of #defines. It's the lack of type
safety I don't like. Maybe it as was a bad experience with come code
that tried to use enems as types, but ended up abusing them (assigning
wrong values) that made me feel this way.

Ian Collins <> writes:
> Keith Thompson wrote:
[...]
>> A C enumerated type doesn't act like an enumerated type in, say,
>> Pascal or Ada, but it's not supposed to. It merely provides a set of
>> names for specific values, and an integral type that can hold all
>> those values.
>>
> Or in C++, where they are first class types. A C enum is little
> different from a typedef and a set of #defines.

Exactly (except that the names of the constants follow the scoping
rules of ordinary identifiers rather than of macros, which IMHO is a
considerable advantage).
> It's the lack of type
> safety I don't like.

Welcome to C! }
> Maybe it as was a bad experience with come code
> that tried to use enems as types, but ended up abusing them (assigning
> wrong values) that made me feel this way.

A C enumerated type is what it is. No more, no less. As long as you
keep that in mind, and *don't* confuse it with similar features in
other languages, they're not that hard to use.

You can have an enumerated type for which only the named values are
considered valid. Assigning some other value is then a logical bug in
your program, one that the compiler unfortunately won't help you
detect (unless you write your own range-checking code). But nothing
else in C will detect this kind of logical error either (unless you
write your own range-checking code). What the "enum" construct gives
you is a convenient way for the compiler to assign consecutive values
to your constants, and to choose a type that can hold all of them.

Or you can have an enumerated type where only some of the valid values
have names assigned to them, and assigning some other value is not an
error:
enum card_rank { ace = 1, jack = 11, queen = 12, king = 13 };

Or you can have an anonymous enumerated type if all you're interested
in is the constants:
enum { MAX_LENGTH = 256 };

It might have made more sense to have three different language
constructs for these three things. But if we were going to insist on
everything making sense, we probably wouldn't be using C.

--
Keith Thompson (The_Other_Keith) <>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!