[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Bit field structures and C++

Marcel Müller

10/20/2008 5:09:00 PM

Hi,

is the following code valid?

#include <stdio.h>

struct X
{ bool f1:1;
bool f2:1;
};

int main(int argc, char* argv[])
{ X x;
x.f1 = true;
x.f2 = false;
printf("%u %u %u\n", x.f1, x.f2, sizeof x);
return 0;
}

While all my compiler seem to eat the combination of bool and bit
fields, it is not that straight forward, because normally it must be an
unsigned integer type. And there is no implicit conversion from that to
bool.

In fact, the compilers also translate the following structure without
warning:

struct X
{ bool f1:2;
bool f2:2;
};


If the code at the top is valid I would like to prefer this over
enumeration types with the usual power of two values.

Unfortunately at least gcc seems not to optimize expressions like
if (x.f2)
in a way to avoid the logical shift.


Marcel
6 Answers

Erik Wikström

10/20/2008 5:52:00 PM

0

On 2008-10-20 19:09, Marcel Müller wrote:
> Hi,
>
> is the following code valid?
>
> #include <stdio.h>
>
> struct X
> { bool f1:1;
> bool f2:1;
> };
>
> int main(int argc, char* argv[])
> { X x;
> x.f1 = true;
> x.f2 = false;
> printf("%u %u %u\n", x.f1, x.f2, sizeof x);
> return 0;
> }
>
> While all my compiler seem to eat the combination of bool and bit
> fields, it is not that straight forward, because normally it must be an
> unsigned integer type. And there is no implicit conversion from that to
> bool.

C++ allows bool bitfields.

> In fact, the compilers also translate the following structure without
> warning:
>
> struct X
> { bool f1:2;
> bool f2:2;
> };
>
>
> If the code at the top is valid I would like to prefer this over
> enumeration types with the usual power of two values.
>
> Unfortunately at least gcc seems not to optimize expressions like
> if (x.f2)
> in a way to avoid the logical shift.

I doubt that there is any way to implement a bitfield without the shift,
and often also masking.

--
Erik Wikström

Marcel Müller

10/20/2008 6:59:00 PM

0

Erik Wikström wrote:
> C++ allows bool bitfields.

OK, thanks.


>> Unfortunately at least gcc seems not to optimize expressions like
>> if (x.f2)
>> in a way to avoid the logical shift.
>
> I doubt that there is any way to implement a bitfield without the shift,
> and often also masking.

In the above case: yes.

If I had implemented the same semantic by an enumeration type, the
condition above would look like
enum Y
{ f1 = 1,
f2 = 2,
};
Y y;
if (y & Y::f2)
or similar. This does not require a shift operation, of course. In the
same way a compiler could optimize the condition
if (x.f2)
by using a mask and a comparsion to zero.
Btw. gcc really does more complex optimizations. E.g. the initial code
int main(int argc, char* argv[])
{ X x;
x.f1 = true;
x.f2 = false;
printf("%u %u %u\n", x.f1, x.f2, sizeof x);
return 0;
}

is in fact translated as
int main(int argc, char* argv[])
{ X x;
x.f1 = true;
x.f2 = false;
printf("%u %u %u\n", 1, 0, 1);
return 0;
}
So gcc realized that x.f1 and x.f2 are in fact constant at the execution
of printf. The same applies to 'if' unless I put it into a subfunction
with an X& argument.


Marcel

James Kanze

10/20/2008 7:56:00 PM

0

On Oct 20, 7:09 pm, Marcel Müller <news.5.ma...@spamgourmet.org>
wrote:
> is the following code valid?

>    #include <stdio.h>

>    struct X
>    {
> bool f1:1;
>      bool f2:1;
>    };

>    int main(int argc, char* argv[])
>    {
> X x;
>      x.f1 = true;
>      x.f2 = false;
>      printf("%u %u %u\n", x.f1, x.f2, sizeof x);
>      return 0;
>    }

> While all my compiler seem to eat the combination of bool and
> bit fields, it is not that straight forward, because normally
> it must be an unsigned integer type. And there is no implicit
> conversion from that to bool.

No implicit conversion of what to bool? In this case, you're
passing a type bool as a vararg. In C++, bool is an integral
type, so integral promotions apply---the actual argument will be
passed as an int with value of either 0 or 1. In C (and I'm
pretty sure in C++ as well), int's and unsigned int's with the
same values have the same representation, and this special case
of type mismatch is legal. (Note that if you passed a negative
value, it would be undefined behavior.)

Of course, in this particular case, C++ offers better
alternatives:
std::cout << x.f1 << ' ' << x.f2 ...

> In fact, the compilers also translate the following structure
> without warning:

>    struct X
>    {
> bool f1:2;
>      bool f2:2;
>    };

Why shouldn't it?

> If the code at the top is valid I would like to prefer this
> over enumeration types with the usual power of two values.

But they don't do the same thing.

> Unfortunately at least gcc seems not to optimize expressions
> like
>    if (x.f2)
> in a way to avoid the logical shift.

That sounds like a problem with the optimizer. I'd ask about it
in a g++ newsgroup, or even post it as a bug report (or an
enhancement request).

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

blargg.h4g

10/20/2008 10:32:00 PM

0

In article <48fcbb41$0$13388$9b4e6d93@newsspool4.arcor-online.net>,
=?ISO-8859-1?Q?Marcel_M=FCller?= <news.5.maazl@spamgourmet.org> wrote:

> Hi,
>
> is the following code valid?
>
> #include <stdio.h>
>
> struct X
> { bool f1:1;
> bool f2:1;
> };
>
> int main(int argc, char* argv[])
> { X x;
> x.f1 = true;
> x.f2 = false;
> printf("%u %u %u\n", x.f1, x.f2, sizeof x);
[...]

BTW, you're passing a size_t where printf() expects an unsigned int. On
machines where size_t is a larger type, like unsigned long, this will
yield undefined behavior. Cast the sizeof to an unsigned int, or use a
type-safe facility like iostream.

Pete Becker

10/21/2008 3:13:00 AM

0

On 2008-10-20 18:32:29 -0400, blargg.h4g@gishpuppy.com (blargg) said:

> In article <48fcbb41$0$13388$9b4e6d93@newsspool4.arcor-online.net>,
> =?ISO-8859-1?Q?Marcel_M=FCller?= <news.5.maazl@spamgourmet.org> wrote:
>
>> Hi,
>>
>> is the following code valid?
>>
>> #include <stdio.h>
>>
>> struct X
>> { bool f1:1;
>> bool f2:1;
>> };
>>
>> int main(int argc, char* argv[])
>> { X x;
>> x.f1 = true;
>> x.f2 = false;
>> printf("%u %u %u\n", x.f1, x.f2, sizeof x);
> [...]
>
> BTW, you're passing a size_t where printf() expects an unsigned int. On
> machines where size_t is a larger type, like unsigned long, this will
> yield undefined behavior. Cast the sizeof to an unsigned int, or use a
> type-safe facility like iostream.

Or use "%zu" for the format specifier, if your version of printf supports C99.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

James Kanze

10/21/2008 8:29:00 AM

0

On Oct 21, 12:32 am, blargg....@gishpuppy.com (blargg) wrote:
> In article <48fcbb41$0$13388$9b4e6...@newsspool4.arcor-online.net>,
> =?ISO-8859-1?Q?Marcel_M=FCller?= <news.5.ma...@spamgourmet.org> wrote:
> > Hi,

> > is the following code valid?

> > #include <stdio.h>

> > struct X
> > { bool f1:1;
> > bool f2:1;
> > };

> > int main(int argc, char* argv[])
> > { X x;
> > x.f1 = true;
> > x.f2 = false;
> > printf("%u %u %u\n", x.f1, x.f2, sizeof x);

> [...]

> BTW, you're passing a size_t where printf() expects an
> unsigned int. On machines where size_t is a larger type, like
> unsigned long, this will yield undefined behavior.

Formally, it has nothing to do with the size of size_t per se.
size_t is a typedef; if it is defined to be unsigned long, you
have undefined behavior, even if the sizes are the same.

> Cast the sizeof to an unsigned int, or use a type-safe
> facility like iostream.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34