473,414 Members | 1,590 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

Question about "enums"

mdh
In one of the answers to a K&R exercise, the first couple of lines are:

enum loop { NO, YES};
enum loop okloop=YES;

I get the first line, but not the second.

Sorry about the LOL question.

Thanks in advance

Apr 30 '06 #1
37 2165
mdh wrote:
In one of the answers to a K&R exercise, the first couple of lines are:

enum loop { NO, YES};
enum loop okloop=YES;

oklopp us a variable of the enum type loop, so you can assign either NO
or YES to it.

--
Ian Collins.
Apr 30 '06 #2
mdh

Ian Collins wrote:

oklopp us a variable of the enum type loop, so you can assign either NO
or YES to it.


It must be late or too much C :-)

I guess what I am missing is what the:

enum loop { YES,NO}

then does?

I thought that the idea behind this was to assign an integer to the
YES, NO? ( In this case 0 and 1?)

Then why not simply use the terms "YES" and "NO"?

Thanks in advance?

Apr 30 '06 #3
mdh wrote:
Ian Collins wrote:
oklopp us a variable of the enum type loop, so you can assign either NO
or YES to it.

It must be late or too much C :-)

I guess what I am missing is what the:

enum loop { YES,NO}

then does?

An enum is a type, which in this case can have one of two values, YES
and NO.

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.
I thought that the idea behind this was to assign an integer to the
YES, NO? ( In this case 0 and 1?)

Then why not simply use the terms "YES" and "NO"?

you can,

int n = YES;

Is perfectly OK.

--
Ian Collins.
Apr 30 '06 #4
mdh wrote:

In one of the answers to a K&R exercise, the first couple of lines
are:

enum loop { NO, YES};
enum loop okloop=YES;

I get the first line, but not the second.


Then separate the second line into its components:

enum loop okloop;

okloop = YES;

and the three lines are: type declaration, var declaration,
assignment.

--
"Churchill and Bush can both be considered wartime leaders, just
as Secretariat and Mr Ed were both horses." - James Rhodes.
"We have always known that heedless self-interest was bad
morals. We now know that it is bad economics" - FDR
Apr 30 '06 #5
mdh

CBFalconer wrote:
Then separate the second line into its components:


Thank you both Ian and CBF for that explanation.

Apr 30 '06 #6
u can make use of okloop whereever u want "1"
if if is not that please correct me

Apr 30 '06 #7
venkatesh wrote:
u can make use of okloop whereever u want "1"
if if is not that please correct me

What are you replying to? Please quote the context.

Assuming you are refereing to:

enum loop { NO, YES};
enum loop okloop=YES;

You would use loop whenever you wanted YES. Use an enum for what it is,
if you wanted a synonym for 1, use a const (unsigned) int.

--
Ian Collins.
Apr 30 '06 #8

Ian Collins wrote:
mdh wrote:
Ian Collins wrote:
oklopp us a variable of the enum type loop, so you can assign either NO
or YES to it.


An enum is a type, which in this case can have one of two values, YES
and NO.

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.


gcc gives a warning when you do a switch on an enum type, indicating
that you have failed to explicitely specify behavior for any of the
listed cases. I find that very useful.

Apr 30 '06 #9
Bill Pursell wrote:
Ian Collins wrote:
mdh wrote:
Ian Collins wrote:
oklopp us a variable of the enum type loop, so you can assign either NO
or YES to it.

An enum is a type, which in this case can have one of two values, YES
and NO.

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.

gcc gives a warning when you do a switch on an enum type, indicating
that you have failed to explicitely specify behavior for any of the
listed cases. I find that very useful.

But not with the following, which I've always considered a huge hole in
the C standard.

enum loop { NO, YES};
enum loop okloop=YES;

void f( enum loop v )
{
}

int main(void)
{
f( 42 );

okloop = 42;

return 0;
}

--
Ian Collins.
Apr 30 '06 #10

Ian Collins wrote:
Bill Pursell wrote:
Ian Collins wrote:

Assigning any other value to <an enum type> is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.

gcc gives a warning when you do a switch on an enum type, indicating
that you have failed to explicitely specify behavior for any of the
listed cases. I find that very useful.

But not with the following, which I've always considered a huge hole in
the C standard.

enum loop { NO, YES};
enum loop okloop=YES;

void f( enum loop v )
{
}

int main(void)
{
f( 42 );

okloop = 42;

return 0;
}


Agreed. I've never written a compiler, but it strikes me that that
should be a fairly simple warning to emit. Does anyone know why such
warnings are not given?

Apr 30 '06 #11
mdh

Ian Collins wrote:

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.

Is this what you mean?

enum months{Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov ,Dec};
enum months mymonths=14; / * Should really raise an outofbounds
exception ? */

printf("I have chosen month %d", mymonths); /* prints 14 */

Apr 30 '06 #12
Ian Collins wrote:
venkatesh wrote:
u can make use of okloop whereever u want "1"
if if is not that please correct me

What are you replying to? Please quote the context.

Assuming you are refereing to:

enum loop { NO, YES};
enum loop okloop=YES;

You would use loop whenever you wanted YES. Use an enum for what it is,
if you wanted a synonym for 1, use a const (unsigned) int.


A const int can't be used in constant expressions. I'll admit declaring
okloop as int in that example is probably not a good idea, but do you
have a problem with unnamed enums used to define constants too?

Apr 30 '06 #13
mdh wrote:
Ian Collins wrote:

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.


Is this what you mean?

enum months{Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov ,Dec};
enum months mymonths=14; / * Should really raise an outofbounds
exception ? */

Yes, it sure does in C++.

--
Ian Collins.
Apr 30 '06 #14
Harald van Dijk wrote:
Ian Collins wrote:
venkatesh wrote:
u can make use of okloop whereever u want "1"
if if is not that please correct me

What are you replying to? Please quote the context.

Assuming you are refereing to:

enum loop { NO, YES};
enum loop okloop=YES;

You would use loop whenever you wanted YES. Use an enum for what it is,
if you wanted a synonym for 1, use a const (unsigned) int.

A const int can't be used in constant expressions.


Another oversight that should have been fixed.
I'll admit declaring
okloop as int in that example is probably not a good idea, but do you
have a problem with unnamed enums used to define constants too?

No, it's the only tidy workaround for the previous oversight.

--
Ian Collins.
Apr 30 '06 #15
Ian Collins wrote:
mdh wrote:

I guess what I am missing is what the:

enum loop { YES,NO}

then does?


An enum is a type, which in this case can have one of two values, YES
and NO.

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.


Assigning values other than the constants declared in the enumeration
are not necessarily undefined by the C Standard. The implementation
must assign the enum to an integer type which will hold all the
enumeration constants. It can hold other integer values as well. An
enum type is basically an integer type and can be used as such.

Having said that, I think it is wise, as a good engineering practice, to
use an enum type to hold only the explicitly declared values.

--
Thad
May 1 '06 #16
Thad Smith wrote:
Ian Collins wrote:
mdh wrote:


I guess what I am missing is what the:

enum loop { YES,NO}

then does?


An enum is a type, which in this case can have one of two values, YES
and NO.

Assigning any other value to a loop is undefined. Unfortunately C
compilers don't regard this as an error, which renders enums little more
than symbolic constants.

Assigning values other than the constants declared in the enumeration
are not necessarily undefined by the C Standard. The implementation
must assign the enum to an integer type which will hold all the
enumeration constants. It can hold other integer values as well. An
enum type is basically an integer type and can be used as such.

Having said that, I think it is wise, as a good engineering practice, to
use an enum type to hold only the explicitly declared values.

Can you think of any good reason for not enforcing that practice?

--
Ian Collins.
May 1 '06 #17
Ian Collins wrote:
Thad Smith wrote:

Assigning values other than the constants declared in the enumeration
are not necessarily undefined by the C Standard. The implementation
must assign the enum to an integer type which will hold all the
enumeration constants. It can hold other integer values as well. An
enum type is basically an integer type and can be used as such.

Having said that, I think it is wise, as a good engineering practice, to
use an enum type to hold only the explicitly declared values.


Can you think of any good reason for not enforcing that practice?


Attempts to assign anything other than an enumeration constant defined
for the associated enumeration type or another enumeration variable of
the same type would be a useful compiler or lint warning. Refusing to
translate in such cases would make the compiler non-conforming.

--
Thad
May 1 '06 #18
Thad Smith wrote:
Ian Collins wrote:
Thad Smith wrote:


Assigning values other than the constants declared in the enumeration
are not necessarily undefined by the C Standard. The implementation
must assign the enum to an integer type which will hold all the
enumeration constants. It can hold other integer values as well. An
enum type is basically an integer type and can be used as such.

Having said that, I think it is wise, as a good engineering practice, to
use an enum type to hold only the explicitly declared values.

Can you think of any good reason for not enforcing that practice?

Attempts to assign anything other than an enumeration constant defined
for the associated enumeration type or another enumeration variable of
the same type would be a useful compiler or lint warning. Refusing to
translate in such cases would make the compiler non-conforming.

Maybe this is a topic for comp.std.c, I still think the C standard is
broken in this instance.

--
Ian Collins.
May 1 '06 #19
Ian Collins <ia******@hotmail.com> writes:
Thad Smith wrote:

[snip]
Attempts to assign anything other than an enumeration constant defined
for the associated enumeration type or another enumeration variable of
the same type would be a useful compiler or lint warning. Refusing to
translate in such cases would make the compiler non-conforming.

Maybe this is a topic for comp.std.c, I still think the C standard is
broken in this instance.


I wouldn't say it's broken. The design of enumerated types isn't
ideal, but I don't think it's possible to fix it (though it would be
possible to invent a new feature that doesn't have the drawbacks of
the current types).

For example:

enum foo { a, b };
enum foo e;
int i = 2;
e = i;

In this case, obj is an object of type "enum foo", and the value of i
is assigned to it. The value being assigned doesn't match any of the
enumerators of the type, but there's no way in general to detect this
at compilation time.

If it's going to be detected at run time, you need to introduce an
entire mechanism for detecting run time errors, something that C
doesn't currently have. And for this particular check, a simple range
check is insufficient; consider replacing the type declaration above
with:

enum foo { a = 1, b = 37 };

C's enumerated types really don't provide much more than a set of
named constants. There are other languages that have more type-safe
enumerated types (Pascal and Ada, for example), but I don't think it's
likely that C's enumerated types can be significantly improved without
breaking existing code (or the language itself).

If you can come up with a proposal, though, by all means go for it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 1 '06 #20
Keith Thompson wrote:
Ian Collins <ia******@hotmail.com> writes:
Thad Smith wrote:
[snip]
Attempts to assign anything other than an enumeration constant defined
for the associated enumeration type or another enumeration variable of
the same type would be a useful compiler or lint warning. Refusing to
translate in such cases would make the compiler non-conforming.


Maybe this is a topic for comp.std.c, I still think the C standard is
broken in this instance.

I wouldn't say it's broken. The design of enumerated types isn't
ideal, but I don't think it's possible to fix it (though it would be
possible to invent a new feature that doesn't have the drawbacks of
the current types).

For example:

enum foo { a, b };
enum foo e;
int i = 2;
e = i;

In this case, obj is an object of type "enum foo", and the value of i
is assigned to it. The value being assigned doesn't match any of the
enumerators of the type, but there's no way in general to detect this
at compilation time.

You could if enumerated types and int where different types without
automatic conversion, which is the way C++ does it, so you simply can't
assign an int to an enum.
If it's going to be detected at run time, you need to introduce an
entire mechanism for detecting run time errors, something that C
doesn't currently have. And for this particular check, a simple range
check is insufficient; consider replacing the type declaration above
with:

enum foo { a = 1, b = 37 };
Again, if the only legal things you can assign to e are foo named
constants, the error can be flagged at compiler time.
C's enumerated types really don't provide much more than a set of
named constants. There are other languages that have more type-safe
enumerated types (Pascal and Ada, for example), but I don't think it's
likely that C's enumerated types can be significantly improved without
breaking existing code (or the language itself).

If you can come up with a proposal, though, by all means go for it.

Simply remove the automatic conversion from an integer type to an
enumerated type. Automatic conversion form enum to integer types should
be permitted because enumerated types are constrained to a set of
integer values. Thus assignment from enum to int doesn't violate any
constraints.

--
Ian Collins.
May 1 '06 #21
Ian Collins <ia******@hotmail.com> writes:
Keith Thompson wrote:
Ian Collins <ia******@hotmail.com> writes: [...]
Maybe this is a topic for comp.std.c, I still think the C standard is
broken in this instance.

I wouldn't say it's broken. The design of enumerated types isn't
ideal, but I don't think it's possible to fix it (though it would be
possible to invent a new feature that doesn't have the drawbacks of
the current types).

For example:

enum foo { a, b };
enum foo e;
int i = 2;
e = i;

In this case, obj is an object of type "enum foo", and the value of i
is assigned to it. The value being assigned doesn't match any of the
enumerators of the type, but there's no way in general to detect this
at compilation time.

You could if enumerated types and int where different types without
automatic conversion, which is the way C++ does it, so you simply can't
assign an int to an enum.


I actually agree that that's a better approach. But you can't make
such a change to C without breaking existing code, something the
committee is very hesitant to do. (They don't always entirely avoid
it; for example, the C99 standard added several new keywords.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 2 '06 #22
Keith Thompson wrote:
Ian Collins <ia******@hotmail.com> writes:
Keith Thompson wrote:
Ian Collins <ia******@hotmail.com> writes:
[...]
Maybe this is a topic for comp.std.c, I still think the C standard is
broken in this instance.
I wouldn't say it's broken. The design of enumerated types isn't
ideal, but I don't think it's possible to fix it (though it would be
possible to invent a new feature that doesn't have the drawbacks of
the current types).

For example:

enum foo { a, b };
enum foo e;
int i = 2;
e = i;

In this case, obj is an object of type "enum foo", and the value of i
is assigned to it. The value being assigned doesn't match any of the
enumerators of the type, but there's no way in general to detect this
at compilation time.


You could if enumerated types and int where different types without
automatic conversion, which is the way C++ does it, so you simply can't
assign an int to an enum.

I actually agree that that's a better approach. But you can't make
such a change to C without breaking existing code, something the
committee is very hesitant to do. (They don't always entirely avoid
it; for example, the C99 standard added several new keywords.)

That's the standard (pun intended) argument.

I'd wager it would break a lot of already broken but not tested code :)

Anyway, there's always the fall back of compiler switchs to disable
language features. These are inevitable whenever a standard is updated.

Being able to use enums as type-safe function parameters is worth the
cost, in my opinion.

--
Ian Collins.
May 2 '06 #23
Ian Collins <ia******@hotmail.com> writes:
Keith Thompson wrote:

<SNIP>
I actually agree that that's a better approach. But you can't make
such a change to C without breaking existing code, something the
committee is very hesitant to do. (They don't always entirely avoid
it; for example, the C99 standard added several new keywords.)

That's the standard (pun intended) argument.

I'd wager it would break a lot of already broken but not tested code :)


Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous range
of integers is legal, but some values are special. For example in an
embedded system I might have a lot of (electrical) signals labelled
0...n. It is quite useful to have the automatic sequential numbering
provided by the enum, also to be able to skip over some "unused", but
still valid, inputs.

enum
{
START=000,
REJECT,
QUEUE,
BRAKE,
/*...*/
ALARM=020,
TEST,
NSIGNALS=040
};

turn_on(REJECT);
turn_off(TEST);

/* hardware test */
for(i=0; i<NSIGNALS; i++)
{
turn_on(i);
delay();
turn_off(i);
}

--

John Devereux
May 2 '06 #24
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:

Keith Thompson wrote:


<SNIP>
I actually agree that that's a better approach. But you can't make
such a change to C without breaking existing code, something the
committee is very hesitant to do. (They don't always entirely avoid
it; for example, the C99 standard added several new keywords.)


That's the standard (pun intended) argument.

I'd wager it would break a lot of already broken but not tested code :)

Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous range
of integers is legal, but some values are special. For example in an
embedded system I might have a lot of (electrical) signals labelled
0...n. It is quite useful to have the automatic sequential numbering
provided by the enum, also to be able to skip over some "unused", but
still valid, inputs.

Nothing wrong with that, I was referring to code that assigned invalid
values to an enum.

--
Ian Collins.
May 2 '06 #25
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:
Keith Thompson wrote:


<SNIP>
I actually agree that that's a better approach. But you can't make
such a change to C without breaking existing code, something the
committee is very hesitant to do. (They don't always entirely avoid
it; for example, the C99 standard added several new keywords.)
That's the standard (pun intended) argument.

I'd wager it would break a lot of already broken but not tested code :)

Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous range
of integers is legal, but some values are special. For example in an
embedded system I might have a lot of (electrical) signals labelled
0...n. It is quite useful to have the automatic sequential numbering
provided by the enum, also to be able to skip over some "unused", but
still valid, inputs.

Nothing wrong with that, I was referring to code that assigned invalid
values to an enum.


Since the C standard allows that, code that does it isn't wrong. It's
perfectly legal, and has well-defined semantics, to assign a value to
an enum object that isn't one of the constants defined for the type
(at least as long as the value is between the lowest and highest
values).

For example:

enum foo { FIRST = 0, LAST = 999 };
enum foo obj;
for (obj = FIRST; obj <= LAST; obj ++) {
...
}

Disallow this usage, and you'll break existing valid code.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 2 '06 #26
Keith Thompson wrote:
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:

Keith Thompson wrote:

<SNIP>

>I actually agree that that's a better approach. But you can't make
>such a change to C without breaking existing code, something the
>committee is very hesitant to do. (They don't always entirely avoid
>it; for example, the C99 standard added several new keywords.)
>

That's the standard (pun intended) argument.

I'd wager it would break a lot of already broken but not tested code :)
Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous range
of integers is legal, but some values are special. For example in an
embedded system I might have a lot of (electrical) signals labelled
0...n. It is quite useful to have the automatic sequential numbering
provided by the enum, also to be able to skip over some "unused", but
still valid, inputs.


Nothing wrong with that, I was referring to code that assigned invalid
values to an enum.

Since the C standard allows that, code that does it isn't wrong. It's
perfectly legal, and has well-defined semantics, to assign a value to
an enum object that isn't one of the constants defined for the type
(at least as long as the value is between the lowest and highest
values).

For example:

enum foo { FIRST = 0, LAST = 999 };
enum foo obj;
for (obj = FIRST; obj <= LAST; obj ++) {
...
}

Disallow this usage, and you'll break existing valid code.

Another construct I'd like to see go the way of the Dodo. But I can see
I'm flogging a dead horse.

--
Ian Collins.
May 2 '06 #27
Keith Thompson a écrit :
Since the C standard allows that, code that does it isn't wrong. It's
perfectly legal, and has well-defined semantics, to assign a value to
an enum object that isn't one of the constants defined for the type
(at least as long as the value is between the lowest and highest
values).

For example:

enum foo { FIRST = 0, LAST = 999 };
enum foo obj;
for (obj = FIRST; obj <= LAST; obj ++) {
...
}

Disallow this usage, and you'll break existing valid code.

Why do not use "int"?

Why use an enum when its value is just an int???

For example:

enum foo { FIRST = 0, LAST = 999 };
int obj;
for (obj = FIRST; obj <= LAST; obj ++) {
...
}

Id enums are of any value then at all times the value of an enum object
must be in the legal values of that enum!

If not there is no use actually besides replacing a #define...
May 2 '06 #28
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:

Keith Thompson wrote:


<SNIP>
I actually agree that that's a better approach. But you can't make
such a change to C without breaking existing code, something the
committee is very hesitant to do. (They don't always entirely avoid
it; for example, the C99 standard added several new keywords.)
That's the standard (pun intended) argument.

I'd wager it would break a lot of already broken but not tested code :)

Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous range
of integers is legal, but some values are special. For example in an
embedded system I might have a lot of (electrical) signals labelled
0...n. It is quite useful to have the automatic sequential numbering
provided by the enum, also to be able to skip over some "unused", but
still valid, inputs.

Nothing wrong with that, I was referring to code that assigned invalid
values to an enum.


But how is the the compiler supposed to *know* they were invalid? In
the code you snipped, I only mentioned the "special" values in the
enum, yet in fact any integer could be "valid".

I thought your suggestion was that compilers should reject assignments
of values that are not in the enum declaration.

--

John Devereux
May 2 '06 #29
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:
Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous range
of integers is legal, but some values are special. For example in an
embedded system I might have a lot of (electrical) signals labelled
0...n. It is quite useful to have the automatic sequential numbering
provided by the enum, also to be able to skip over some "unused", but
still valid, inputs.

Nothing wrong with that, I was referring to code that assigned invalid
values to an enum.

But how is the the compiler supposed to *know* they were invalid? In
the code you snipped, I only mentioned the "special" values in the
enum, yet in fact any integer could be "valid".

Sorry if I got carried away with the snippers...

The compiler would know because it knows the legal set of values for the
enumeration. For this to work, math operations on enums will have to be
removed. In my opinion, they don't make sense, given a set of integers
{ 1, 5, 7, 9 } what does incrementing a member of the set do?

Restoring your code:

enum
{
START=000,
REJECT,
QUEUE,
BRAKE,
/*...*/
ALARM=020,
TEST,
NSIGNALS=040
};

turn_on(REJECT);
turn_off(TEST);

/* hardware test */
for(i=0; i<NSIGNALS; i++)
{
turn_on(i);
delay();
turn_off(i);
}

I had assumed that i was an int (you didn't show the declaration).
I thought your suggestion was that compilers should reject assignments
of values that are not in the enum declaration.


Indeed it is.

--
Ian Collins.
May 2 '06 #30
jacob navia <ja***@jacob.remcomp.fr> writes:
Keith Thompson a écrit :
Since the C standard allows that, code that does it isn't wrong. It's
perfectly legal, and has well-defined semantics, to assign a value to
an enum object that isn't one of the constants defined for the type
(at least as long as the value is between the lowest and highest
values).
For example:
enum foo { FIRST = 0, LAST = 999 };
enum foo obj;
for (obj = FIRST; obj <= LAST; obj ++) {
...
}
Disallow this usage, and you'll break existing valid code.


Why do not use "int"?

Why use an enum when its value is just an int???

For example:

enum foo { FIRST = 0, LAST = 999 };
int obj;
for (obj = FIRST; obj <= LAST; obj ++) {
...
}

Id enums are of any value then at all times the value of an enum
object must be in the legal values of that enum!

If not there is no use actually besides replacing a #define...


Enumerated types have a number of advantages over #define. They
automatically assign unique values to each of a sequence of names; you
can do that manually with macros, but it's inconvenient. They're
scoped; macros are visible from the point of definition to the end of
the translation unit. And the compiler takes care of choosing a type
that fits all the specified values.

Certainly the code you suggest is perfectly valid, and probably better
than the example I presented. And if I were designing a new language
from scratch, enums would be distinct types, and there would be no
implicit conversions between enums and integers.

Although C's definition of enumerated types has some real weaknesses,
I don't think it's broken enough to justify changing it -- at least
not in a language that calls itself "C".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 2 '06 #31
Ian Collins opined:
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:

Don't know if it's "broken", but I do regularly make use of this
"feature" of enum. Often I have a situation where a contiguous
range of integers is legal, but some values are special. For
example in an embedded system I might have a lot of (electrical)
signals labelled 0...n. It is quite useful to have the automatic
sequential numbering provided by the enum, also to be able to skip
over some "unused", but still valid, inputs.
Nothing wrong with that, I was referring to code that assigned
invalid values to an enum.

But how is the the compiler supposed to *know* they were invalid? In
the code you snipped, I only mentioned the "special" values in the
enum, yet in fact any integer could be "valid".

Sorry if I got carried away with the snippers...

The compiler would know because it knows the legal set of values for
the enumeration. For this to work, math operations on enums will
have to be removed. In my opinion, they don't make sense, given a
set of integers { 1, 5, 7, 9 } what does incrementing a member of the
set do?


Well, for an `enum` it may make sense to "walk" through the list of
allowed values (i.e. `5` + 1 == `7`, in the example above). A bit like
pointer arithmetic, I guess.

I don't see why would that be so useful to make it into the language,
though. And, it would likely break a *lot* of existing code.

IMHO, as they stand `enum`s in C are a bit flawed, but still useful.

--
"How should I know if it works? That's what beta testers are for. I
only coded it."
(Attributed to Linus Torvalds, somewhere in a posting)

<http://clc-wiki.net/wiki/Introduction_to_comp.lang.c>

May 2 '06 #32
Ian Collins wrote:
Bill Pursell wrote:
gcc gives a warning when you do a switch on an enum type, indicating
that you have failed to explicitely specify behavior for any of the
listed cases. I find that very useful.


But not with the following, which I've always considered a huge hole in
the C standard.

enum loop { NO, YES};
enum loop okloop=YES;

void f( enum loop v )
{
}

int main(void)
{
f( 42 );

okloop = 42;

return 0;
}


Compared to other pitfalls in C I think this is a minor one. Note that
the language designer maestro N. Wirth even omitted enumerations in
Oberon (successor to Modula).

Reference: http://www.oberon2005.ru/paper/nw1988d.pdf
August
May 2 '06 #33
August Karlstrom wrote:
Ian Collins wrote:
Bill Pursell wrote:
gcc gives a warning when you do a switch on an enum type, indicating
that you have failed to explicitely specify behavior for any of the
listed cases. I find that very useful.


But not with the following, which I've always considered a huge hole in
the C standard.

enum loop { NO, YES};
enum loop okloop=YES;

void f( enum loop v )
{
}

int main(void)
{
f( 42 );

okloop = 42;

return 0;
}


Compared to other pitfalls in C I think this is a minor one.


Not so much a pitfall as a missed opportunity...

--
Ian Collins.
May 3 '06 #34

Thad Smith wrote:
Ian Collins wrote:
Thad Smith wrote:

Assigning values other than the constants declared in the enumeration
are not necessarily undefined by the C Standard. The implementation
must assign the enum to an integer type which will hold all the
enumeration constants. It can hold other integer values as well. An
enum type is basically an integer type and can be used as such.

Having said that, I think it is wise, as a good engineering practice, to
use an enum type to hold only the explicitly declared values.


Can you think of any good reason for not enforcing that practice?


Attempts to assign anything other than an enumeration constant defined
for the associated enumeration type or another enumeration variable of
the same type would be a useful compiler or lint warning. Refusing to
translate in such cases would make the compiler non-conforming.

One problem with this is storing an enum in a file. Obviously, there is
no fprintf format code for a user-defined enum, so normally something
like %d is used when portability is needed (first casting to int). When
reading back from the file, the safe and portable way is to fscanf back
into an int, and then assigning the int to an enum. The suggestion
above would make it very difficult to store any enum in a file.

May 3 '06 #35
ais523 wrote:
Thad Smith wrote:

Ian Collins wrote:
Thad Smith wrote:

Assigning values other than the constants declared in the enumeration
are not necessarily undefined by the C Standard. The implementation
must assign the enum to an integer type which will hold all the
enumeration constants. It can hold other integer values as well. An
enum type is basically an integer type and can be used as such.

Having said that, I think it is wise, as a good engineering practice, to
use an enum type to hold only the explicitly declared values.

Can you think of any good reason for not enforcing that practice?


Attempts to assign anything other than an enumeration constant defined
for the associated enumeration type or another enumeration variable of
the same type would be a useful compiler or lint warning. Refusing to
translate in such cases would make the compiler non-conforming.


One problem with this is storing an enum in a file. Obviously, there is
no fprintf format code for a user-defined enum, so normally something
like %d is used when portability is needed (first casting to int). When
reading back from the file, the safe and portable way is to fscanf back
into an int, and then assigning the int to an enum. The suggestion
above would make it very difficult to store any enum in a file.

The same problem exists in C++, a simple cast is the solution.

--
Ian Collins.
May 3 '06 #36
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:

Ian Collins <ia******@hotmail.com> writes:
Nothing wrong with that, I was referring to code that assigned invalid
values to an enum.
But how is the the compiler supposed to *know* they were invalid? In
the code you snipped, I only mentioned the "special" values in the
enum, yet in fact any integer could be "valid".

Sorry if I got carried away with the snippers...

The compiler would know because it knows the legal set of values for the
enumeration. For this to work, math operations on enums will have to be
removed. In my opinion, they don't make sense, given a set of integers
{ 1, 5, 7, 9 } what does incrementing a member of the set do?

Restoring your code:

enum
{
START=000,
REJECT,
QUEUE,
BRAKE,
/*...*/
ALARM=020,
TEST,
NSIGNALS=040
};

turn_on(REJECT);
turn_off(TEST);

/* hardware test */
for(i=0; i<NSIGNALS; i++)
{
turn_on(i);
delay();
turn_off(i);
}

I had assumed that i was an int (you didn't show the declaration).


Sorry, yes, i was an int. But turn_off() could be declared a taking an
enum argument. But actually I suppose it could just as well be
declared taking an int, and in fact that is what I do in practice.
I thought your suggestion was that compilers should reject assignments
of values that are not in the enum declaration.


Indeed it is.


So it would be OK to convert an enum to an arbitrary int, but not an
int to an enum type?

--

John Devereux
May 3 '06 #37
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:


So it would be OK to convert an enum to an arbitrary int, but not an
int to an enum type?

Yes, that's what I'd like to see. This makes enums appropriate for use
as a type safe function parameter.

--
Ian Collins.
May 3 '06 #38

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Harold Hsu | last post by:
Hi, Originally, I have defined the following Enum within a namespace (outside a class): Public Enum UserRole Admin Manager User End Enum
4
by: Jon Slaughter | last post by:
is there a simple way to "step" through enums? I have a button that I want to click and have it "cycle" through a set of states defined by enums but the only way I can think of doing this...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.