C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using enum's as bit fields

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Julio M. Merino Vidal
Guest





PostPosted: Sun Apr 25, 2004 1:35 am    Post subject: Using enum's as bit fields Reply with quote



Hi all,

in C, it's common practice to use an enumeration to define several
values as a bit field, and then use the enumeration type to define
function parameters or variables. Consider the following example:

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

int
main(void)
{
enum ENUMTEST e;

e = bit0 | bit2;

return 0;
}

Now, compile it as C and as C++:

[dawn tmp] $ cc -Wall test.c
[dawn tmp] $ c++ -Wall test.c
test.c: In function `int main()':
test.c:12: error: invalid conversion from `int' to `ENUMTEST'

I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

Thanks!

--
Julio M. Merino Vidal The NetBSD Project - http://www.NetBSD.org/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Sam Holden
Guest





PostPosted: Sun Apr 25, 2004 8:33 am    Post subject: Re: Using enum's as bit fields Reply with quote



On 24 Apr 2004 21:35:53 -0400, Julio M. Merino Vidal <jmmv (AT) menta (DOT) net> wrote:
Quote:
Hi all,

in C, it's common practice to use an enumeration to define several
values as a bit field, and then use the enumeration type to define
function parameters or variables. Consider the following example:

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

int
main(void)
{
enum ENUMTEST e;

e = bit0 | bit2;

return 0;
}

Now, compile it as C and as C++:

[dawn tmp] $ cc -Wall test.c
[dawn tmp] $ c++ -Wall test.c
test.c: In function `int main()':
test.c:12: error: invalid conversion from `int' to `ENUMTEST'

I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

const int bit0 = 1 << 0;
const int bit1 = 1 << 1;
const int bit2 = 1 << 2;


--
Sam Holden

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dhruv Matani
Guest





PostPosted: Sun Apr 25, 2004 8:36 am    Post subject: Re: Using enum's as bit fields Reply with quote



On Sat, 24 Apr 2004 21:35:53 -0400, Julio M. Merino Vidal wrote:

Quote:
Hi all,

in C, it's common practice to use an enumeration to define several
values as a bit field, and then use the enumeration type to define
function parameters or variables. Consider the following example:

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

int
main(void)
{
enum ENUMTEST e;

e = bit0 | bit2;

bit0 | bit2 is NOT a member of the enum.

Quote:
return 0;
}

Now, compile it as C and as C++:

[dawn tmp] $ cc -Wall test.c
[dawn tmp] $ c++ -Wall test.c
test.c: In function `int main()':
test.c:12: error: invalid conversion from `int' to `ENUMTEST'

I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

Use bit-fields as mentioned by the standard:

struct bif_f
{
bit0 : 3;
bit1 : 3;
bit2 : 3;
};


--
Regards,
-Dhruv.

Proud to be a Vegetarian.
http://www.vegetarianstarterkit.com/
http://www.vegkids.com/vegkids/index.html


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Andrei Alexandrescu (See
Guest





PostPosted: Sun Apr 25, 2004 10:31 pm    Post subject: Re: Using enum's as bit fields Reply with quote

"Julio M. Merino Vidal" <jmmv (AT) menta (DOT) net> wrote

[snip]
Quote:
I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

You can define operator| and operator& for your enumeration type to perform
the cast internally. The advantage is that you get typesafe combining and
extracting operations.

Andrei



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Sun Apr 25, 2004 10:41 pm    Post subject: Re: Using enum's as bit fields Reply with quote

Julio M. Merino Vidal wrote:
Quote:
enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

enum ENUMTEST e;
e = bit0 | bit2;
return 0;

Now, compile it as C and as C++:

[dawn tmp] $ cc -Wall test.c
[dawn tmp] $ c++ -Wall test.c
test.c: In function `int main()':
test.c:12: error: invalid conversion from `int' to `ENUMTEST'

I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

There are three things that come to my mind: one is bitfields, one is
std::bitfield<> and the other still uses enums.

The first is mostly
struct lowlevel
{
unsigned bit0:1;
unsigned bit1:1;
};

But you still can't use | on it yet. Skipping the second variant, we come
to the third (which also completes the first) and that is simply a matter
of adding an overloaded operator| like this:

enum test;
test operator|(test const& t1, test const& t2)
{
return static_cast<test>(
static_cast<int>(t1)|static_cast<int>(t2) );
}

Uli

--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Sun Apr 25, 2004 11:05 pm    Post subject: Re: Using enum's as bit fields Reply with quote

"Julio M. Merino Vidal" <jmmv (AT) menta (DOT) net> writes:

Quote:
Hi all,

in C, it's common practice to use an enumeration to define several
values as a bit field, and then use the enumeration type to define
function parameters or variables. Consider the following example:

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};
[snip]



enum test
{
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

test operator|(test lhs, test rhs)
{
return test(static_cast }


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dave Harris
Guest





PostPosted: Sun Apr 25, 2004 11:14 pm    Post subject: Re: Using enum's as bit fields Reply with quote

[email]jmmv (AT) menta (DOT) net[/email] (Julio M. Merino Vidal) wrote (abridged):
Quote:
I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

You can add operate|() and put the cast in there.

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

ENUMTEST operator|( ENUMTEST lhs, ENUMTEST rhs ) {
return ENUMTEST( int(lhs) | int(rhs) );
}

-- Dave Harris, Nottingham, UK

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Sun Apr 25, 2004 11:23 pm    Post subject: Re: Using enum's as bit fields Reply with quote

In message <pan.2004.04.25.04.04.03.256017 (AT) gmx (DOT) net>, Dhruv Matani
<dhruvbird (AT) gmx (DOT) net> writes
Quote:
main(void)
{
enum ENUMTEST e;

e = bit0 | bit2;

bit0 | bit2 is NOT a member of the enum.

Yes but understanding why helps to provide a solution. The value of
(bit0 | bit2) most certainly is a legitimate value for ENUMTEST (the
Standard was carefully written so that would be true) but if no
operator| has been defined for ENUMTEST it uses the builtin operator|
for int which evaluates to an int.

For safety reasons C++ (unlike C) does not allow implicit conversions
from int to an enum type. The solution for C compatibility when you
really want is:

#ifdef __cplusplus
inline ENUMTEST operator|(ENUMTEST e1, ENUMTEST e2){
return ENUMTEST((int)e1 | (int)e2);
}

// add similar definitions for any other operators you want
// to use on ENUMTEST
#endif

Now a C++ compiler will see those explicit overloads and use them while
a C compiler will just use its own (type unsafe) alternative.



--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Carl Barron
Guest





PostPosted: Sun Apr 25, 2004 11:24 pm    Post subject: Re: Using enum's as bit fields Reply with quote

Julio M. Merino Vidal <jmmv (AT) menta (DOT) net> wrote:

Quote:
Hi all,

in C, it's common practice to use an enumeration to define several
values as a bit field, and then use the enumeration type to define
function parameters or variables. Consider the following example:

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

int
main(void)
{
enum ENUMTEST e;

e = bit0 | bit2;

return 0;
}

Now, compile it as C and as C++:

[dawn tmp] $ cc -Wall test.c
[dawn tmp] $ c++ -Wall test.c
test.c: In function `int main()':
test.c:12: error: invalid conversion from `int' to `ENUMTEST'

I can use an explicit cast when setting e's value (to avoid the error),
but I don't like this approach. Is it there another way to do this same
thing in C++? Or should I use std::bitfiled instead?

Thanks!
Since C++ requires an explicit cast and C does not you could do this

in a header, and it should produce the same results in C or C++.

typedef enum E_t
{
bit0=1,bit2=2,bit3=4
} E;

#ifdef __cplusplus
inline E operator | (E x,E y) {return static_cast inline E operator & (E x,E y) {return static_cast<E>(x&y);}
// other bitwise operators if desired.
#endif



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dhruv Matani
Guest





PostPosted: Mon Apr 26, 2004 8:24 am    Post subject: Re: Using enum's as bit fields Reply with quote

On Sun, 25 Apr 2004 19:23:52 -0400, Francis Glassborow wrote:

Quote:
In message <pan.2004.04.25.04.04.03.256017 (AT) gmx (DOT) net>, Dhruv Matani
[email]dhruvbird (AT) gmx (DOT) net[/email]> writes
main(void)
{
enum ENUMTEST e;

e = bit0 | bit2;

bit0 | bit2 is NOT a member of the enum.

Yes but understanding why helps to provide a solution. The value of
(bit0 | bit2) most certainly is a legitimate value for ENUMTEST (the
Standard was carefully written so that would be true) but if no
operator| has been defined for ENUMTEST it uses the builtin operator|
for int which evaluates to an int.

Meaning that all values < bit3 (filled in filly by 1) are valid for the
enum?

So, all values < 111(2) => 7 are valid?

I did not know about this! Thanks ;-)


--
Regards,
-Dhruv.

Proud to be a Vegetarian.
http://www.vegetarianstarterkit.com/
http://www.vegkids.com/vegkids/index.html


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Mon Apr 26, 2004 10:18 am    Post subject: Re: Using enum's as bit fields Reply with quote

In message <1gcrvxh.1uas4c31156ymuN%cbarron3 (AT) ix (DOT) netcom.com>, Carl Barron
<cbarron3 (AT) ix (DOT) netcom.com> writes
Quote:
#ifdef __cplusplus
inline E operator | (E x,E y) {return static_cast<E>(x|y);}

Unfortunately that creates a recursive definition so you must also apply
a cast to x and y.

Quote:
inline E operator & (E x,E y) {return static_cast<E>(x&y);}

Ditto.

Quote:
// other bitwise operators if desired.
#endif

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Mon Apr 26, 2004 2:36 pm    Post subject: Re: Using enum's as bit fields Reply with quote

In message <pan.2004.04.26.04.02.48.68958 (AT) gmx (DOT) net>, Dhruv Matani
<dhruvbird (AT) gmx (DOT) net> writes
Quote:
Meaning that all values < bit3 (filled in filly by 1) are valid for the
enum?

So, all values < 111(2) => 7 are valid?

Yes the Standard makes it clear that all values that can be expressed by
the smallest bit-field that could represent all the enumerators are
valid values for the enum type.

Quote:

I did not know about this! Thanks Wink

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michael Jørgensen
Guest





PostPosted: Thu Apr 29, 2004 10:35 pm    Post subject: Re: Using enum's as bit fields Reply with quote


"Julio M. Merino Vidal" <jmmv (AT) menta (DOT) net> wrote

Quote:
Hi all,

in C, it's common practice to use an enumeration to define several
values as a bit field, and then use the enumeration type to define
function parameters or variables. Consider the following example:

enum ENUMTEST {
bit0 = 1 << 0,
bit1 = 1 << 1,
bit2 = 1 << 2
};

Just a word of caution:

I've been bitten hard with the fact that sizeof(ENUMTEST) is different in C
and C++.

I once had some similar enumerations defined in a common header file that
was #included from regular C files and from C++ files. Furthermore, this
enumeration was part of a structure that was passed between functions in the
two groups of source files.

Because the enumeration had different size, the layout of the structure was
different in the two groups of files. This led to hard-to-find bugs.

I realize this is specified quite clearly in the standard, but it was a very
unpleasant surprise to me. Furthermore, it was not trivial to solve, because
the C functions were legacy code, not changeable.

Since then I've learnt to be very careful when using enumerations,
particularly whenever there are any C files around.

-Michael.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Dennett
Guest





PostPosted: Sun May 02, 2004 11:01 am    Post subject: Re: Using enum's as bit fields Reply with quote

Michael Jørgensen wrote:

Quote:

Just a word of caution:

I've been bitten hard with the fact that sizeof(ENUMTEST) is different in C
and C++.

I once had some similar enumerations defined in a common header file that
was #included from regular C files and from C++ files. Furthermore, this
enumeration was part of a structure that was passed between functions in the
two groups of source files.

Because the enumeration had different size, the layout of the structure was
different in the two groups of files. This led to hard-to-find bugs.

I realize this is specified quite clearly in the standard, but it was a very
unpleasant surprise to me. Furthermore, it was not trivial to solve, because
the C functions were legacy code, not changeable.

Since then I've learnt to be very careful when using enumerations,
particularly whenever there are any C files around.

Indeed, some C++ compilers have an option to force all enums
to be a particular size, which can be the most practical
solution when interoperating with C code which relies on this.

-- James

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.