473,385 Members | 1,324 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,385 software developers and data experts.

Enums without identifier, enums and typedef


I came over this code which puzzled me. Isn't the enum supposed to
have an identifier?

enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
Following this, I played around a bit, and came up with the program
below, which I had hoped would provoke the compiler into issuing a
warning about type mismatch (or something along those lines). Which
it didn't. (gcc -std=c99 -Wall -pedantic).

Care to comment?

With kind regards
Asbjørn Sæbø
#include <stdio.h>

typedef enum
{
M_A = 1,
M_B,
M_C,
M_D
} M_type;
typedef enum
{
N_A = 1,
N_B,
N_C,
N_D
} N_type;
void myfunc(M_type myvar)
{
printf("Inside myfunc, myvar is %d\n", myvar);
}
int main(void)
{
N_type a = N_B;

myfunc(a); /* Feed variable of N_type into function expecting M_type */
return 0;
}
Jan 19 '07 #1
10 9536
=?utf-8?b?QXNiasO4cm4gU8OmYsO4?= <in*****@invalid.invalidwrote:
I came over this code which puzzled me. Isn't the enum supposed to
have an identifier?
Not necessarily.
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
This doesn't define a type, but it does define a number of constants.
This can on occasion be quite useful. It is, for example, easier to
maintain than a series of #defines.

Richard
Jan 19 '07 #2

Asbjørn Sæbø wrote:
I came over this code which puzzled me. Isn't the enum supposed to
have an identifier?

enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
Does the FAQ entry <http://c-faq.com/struct/enumvsdefine.htmlhelp?

Basically, I think it boils down to this - enums are for historical
reasons, rather weakly specified. So in effect, you are just creating
some integral constants here. Likewise in your example program, because
of the weak specification values from one enum can be used where
another is specified - enum types are "just" some integer type.

Jan 19 '07 #3
ma**********@pobox.com writes:
[...]
Does the FAQ entry <http://c-faq.com/struct/enumvsdefine.htmlhelp?
Yes. Although this probably means that the practice I have seen of
typedef-ings enums does not help much when it comes to catching
errors.

Thanks, both to you and Richard Bos.

Asbjørn S.
Jan 19 '07 #4
"Asbjørn Sæbø" <in*****@invalid.invalidwrote in message
news:rg*************@ardbeg.nordicsemi.no...
>
I came over this code which puzzled me. Isn't the enum supposed to
have an identifier?

enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
Looks fine to me.

I don't know the standards -- I just have years of messing around with
compilers.

Based on years of messing around and randomly modifying code until it seems
to work most of the time ... an enum is generally interchangeable with an
integer, and the compiler won't enforce type. Passing an integer where an
enum is "expected" or passing an enumerated constant where an integer is
expected seems to generate no warnings or errors.

I don't know the standards, but the code excerpt above behaves about the
same as:

#define BT_CONNECTED (1)
#define BT_OPEN (2)
etc.

The only advantage to enums seems to be that they allow the compiler to
number the constants itself. In fact, in the example you gave, my code
would also traditionally include a symbol like "BT_MAX" at the end to test
for a corrupted or unexpected variable (and of course, the value of BT_MAX
will be modified if constants are added or removed earlier in the list).

Enums in C are treated oddly--the typing is very weak. The automatic
numbering of the constants is the only aspect of it I've found useful.

--
David T. Ashley (dt*@e3ft.com)
http://www.e3ft.com (Consulting Home Page)
http://www.dtashley.com (Personal Home Page)
http://gpl.e3ft.com (GPL Publications and Projects)
Jan 19 '07 #5
Asbjørn Sæbø <in*****@invalid.invalidwrites:
I came over this code which puzzled me. Isn't the enum supposed to
have an identifier?

enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
Perfectly legal. The tag on an enum type declaration is optional.
The declaration creates a type (an anonymous one in this case),
but the constants BT_CONNECTED et al are actually of type int.

For the above declaration, the creation of the type (which can't be
used anyway) is a side effect; the purpose of the declaration is to
declare the constants. It's a cleaner alternatve to

#define BT_CONNECTED 1
#define BT_OPEN 2
...
Following this, I played around a bit, and came up with the program
below, which I had hoped would provoke the compiler into issuing a
warning about type mismatch (or something along those lines). Which
it didn't. (gcc -std=c99 -Wall -pedantic).
[...]
>
#include <stdio.h>

typedef enum
{
M_A = 1,
M_B,
M_C,
M_D
} M_type;
typedef enum
{
N_A = 1,
N_B,
N_C,
N_D
} N_type;
void myfunc(M_type myvar)
{
printf("Inside myfunc, myvar is %d\n", myvar);
}
int main(void)
{
N_type a = N_B;

myfunc(a); /* Feed variable of N_type into function expecting M_type */
return 0;
}
There's no problem with the code. Values of enum or integer types may
be implicitly converted back and forth.

It would have been nice, in some ways, if the rules for enumerated
types were more strict (as they are in some other languages), but
they're not.

--
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.
Jan 19 '07 #6
Asbjørn Sæbø <in*****@invalid.invalidwrites:
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
Putting this in a comment is perverse. I would write this as:
BT_CONNECTED = TCP_ESTABLISHED,
and then there's no need for the comment at all.
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Jan 19 '07 #7
In article <87************@blp.benpfaff.org>,
Ben Pfaff <bl*@cs.stanford.eduwrote:
>enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */

Putting this in a comment is perverse. I would write this as:
BT_CONNECTED = TCP_ESTABLISHED,
and then there's no need for the comment at all.
Assuming that TCP_ESTABLISHED is defined at that point, which it might
well not be.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 19 '07 #8
Asbjørn Sæbø wrote:
ma**********@pobox.com writes:
>[...]
Does the FAQ entry <http://c-faq.com/struct/enumvsdefine.htmlhelp?

Yes. Although this probably means that the practice I have seen of
typedef-ings enums does not help much when it comes to catching
errors.
gcc (and all others out there too, probably) checks switch statements
for you:

typedef enum {
ONE,
TWO
} Something;

void func (Something s)
{
switch (s)
{
case ONE:
break;
} /* warning here - TWO not handled in switch */
}

And using enum type instead of int is a good documentation too,
which is a great help to *avoid* errors in the first place.

Regards,
Yevgen
Jan 19 '07 #9
Asbjørn Sæbø <in*****@invalid.invalidwrites:
ma**********@pobox.com writes:
[...]
Does the FAQ entry <http://c-faq.com/struct/enumvsdefine.htmlhelp?

Yes. Although this probably means that the practice I have seen of
typedef-ings enums does not help much when it comes to catching
errors.
As far as I can tell, typedef-ing an enum doesn't help *at all* when
it comes to catching errors. A typedef merely creates an alias for a
type; it doesn't create a new type.

Typedefs can be useful when creating an abstract data type (hiding the
representation details from clients), or when specifying a numeric
type that may vary from one implementation to another (such as
int32_t, which could be int, long, etc.) Most other uses of typedefs
are, in my opinion, not useful; you might as well refer to the
original type directly.

--
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.
Jan 20 '07 #10
"David T. Ashley" <dt*@e3ft.comwrites:
"Asbjørn Sæbø" <in*****@invalid.invalidwrote in message
news:rg*************@ardbeg.nordicsemi.no...

I came over this code which puzzled me. Isn't the enum supposed to
have an identifier?

enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
[snip]
I don't know the standards, but the code excerpt above behaves about the
same as:

#define BT_CONNECTED (1)
#define BT_OPEN (2)
etc.
Yes, pretty much. Incidentally, the parentheses aren't necessary.
Parenthesizing macro definitions is an excellent habit, but it's good
to know that if the definition is a single literal constant, there's
no way for operator precedence to cause problems.

Of course the parentheses are harmless; this is an idle comment, not a
complaint.
The only advantage to enums seems to be that they allow the compiler to
number the constants itself.
Yup.
In fact, in the example you gave, my code
would also traditionally include a symbol like "BT_MAX" at the end to test
for a corrupted or unexpected variable (and of course, the value of BT_MAX
will be modified if constants are added or removed earlier in the list).
Which you can do like this:

enum {
BT_MIN = 1,
BT_CONNECTED = BT_MIN,
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED,
BT_MAX = BT_CLOSED
};

You still have to fix things if you change the first or last literal,
but not if you add or remove something in the middle.

--
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.
Jan 20 '07 #11

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

Similar topics

27
by: Mark A. Gibbs | last post by:
i have been toying with the idea of making my enums smarter - ie, more in line with the rest of the language. i haven't tested it yet, but what i came up with is a template like this: template...
7
by: narshe | last post by:
I haven't come across an elegant way to do this yet, and would like to know what other people have come up with. There are two tables: CREATE TABLE EmployeeStatus ( pkId int not null primary...
1
by: MariuszC | last post by:
Hello, I have used some library where is defined enum like: typedef enum Enum1 { ENUM1_1, ENUM1_2, ENUM1_3, ENUM1_4, ENUM1_5 }; In my code I have defined: typedef enum Enum2 { ENUM2_1,...
7
by: Victor Eijkhout | last post by:
Intel icc seems to think that enums are not ints: #include <stdlib.h> typedef enum { TRUE=1, FALSE=0 } Truth; #undef __FUNCT__ #define __FUNCT__ "getcontrols" int getcontrols(Truth...
2
by: aiooua | last post by:
hello, I had a doubt regarding the handling of enums in std::map. Consider the following piece of code: ------ #include<iostream> #include<map> using namespace std; typedef enum {
11
by: borophyll | last post by:
Hi all, what is the meaning of the second form of an enum declaration enum identifier { enumerator-list } enum identifier { enumerator-list , } as described in the spec. I couldn't see...
9
by: copx | last post by:
C's enum type disappoints me a lot. You cannot define which type of integer variable is used. This contradicts C's low level spirit. "I want a number variable. I do not care about size or...
8
by: Daniel Gutson | last post by:
Hi, I just wanted to share another library for doing type-safe bitwise operations in C++: http://bitwise-enum.googlecode.com I found it useful, so hopefully it'll be for somebody else as well....
21
by: Thomas Pornin | last post by:
Hello, with gcc-4.2.3, this does not compile: typedef int foo; int f(foo) int foo; { return foo; }
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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...

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.