pragma pack and bitfields

G

Giovanni Bajo

Hello,

with Visual Studio .NET 2003:

__declspec(align(1))
struct X {
unsigned int x : 3;
unsigned int y : 13;
};

sizeof(X) is 4, even with /Zp1 and/or pragma pack(1). I would expect it to
be 2.

Is there any way I can get the behaviour I need? It looks like I'm forced to
use short* and manually extract the bits. FYI, this works with GCC as
expected.

Thanks,
Giovanni Bajo
 
D

David Lowndes

with Visual Studio .NET 2003:
__declspec(align(1))
struct X {
unsigned int x : 3;
unsigned int y : 13;
};

sizeof(X) is 4, even with /Zp1 and/or pragma pack(1). I would expect it to
be 2.

unsigned int is 4 bytes.
Is there any way I can get the behaviour I need?

use unsigned short for the structure member type.

Dave
 
C

Carl Daniel [VC++ MVP]

Giovanni said:
Is there any way I can get the behaviour I need? It looks like I'm
forced to use short* and manually extract the bits. FYI, this works
with GCC as expected.

I don't think so, not unless you change the element types to unsigned short
as David suggests.

This is all implementation defined according to the standard, so VC's
behavior is completely conforming, if not what you hoped for.

-cd
 
G

Giovanni Bajo

David Lowndes wrote:

use unsigned short for the structure member type.


Thanks! Silly me for not thinking of this. I'll try ASAP.

Then, I have another question:

-----------------------------------------------
enum State { ZERO, ONE, TWO };

struct A {
State s : 2;
};

void foo(A a) {
a.s = TWO;
if (a.s != TWO)
abort();
}
-----------------------------------------------

This aborts. The reason has surely to do with the underlying integer type of
the bitfield being signed, so that basically 's' represents "-2" after
assignment, and fails the comparison with two. Do you have a workaround for a
situation like this? GCC works as expected.
 
G

Giovanni Bajo

Carl said:
I don't think so, not unless you change the element types to unsigned
short as David suggests.

This is all implementation defined according to the standard, so VC's
behavior is completely conforming, if not what you hoped for.

Yes, I was not questioning VC standard conforming, rather its implementation
defined choices. Besides standard conformance, there are QoI matters: the way
it behaves in things the standard leaves as implementation defined is still
very important.

In this case, there would be a problem if there was no way to do what I
described. Using David's solution fits my needs (having a struct which matches
the layout of memory data which is beyond my control and which I need to
access), so everything is fine.
 
D

David Lowndes

-----------------------------------------------
enum State { ZERO, ONE, TWO };

struct A {
State s : 2;
};

void foo(A a) {
a.s = TWO;
if (a.s != TWO)
abort();
}
-----------------------------------------------

This aborts. The reason has surely to do with the underlying integer type of
the bitfield being signed, so that basically 's' represents "-2" after
assignment, and fails the comparison with two. Do you have a workaround for a
situation like this?

Other than not using the enum as the bitfield type or otherwise
fiddling with the value, I'm afraid not.
GCC works as expected.

I can imagine reasons for both possibilities, but I'm not familiar
enough with the C++ standards to know what it really should be.

Carl, can you comment on this?

Dave
 
C

Carl Daniel [VC++ MVP]

David said:
I can imagine reasons for both possibilities, but I'm not familiar
enough with the C++ standards to know what it really should be.

Carl, can you comment on this?

It's a bug (thatnks for reminding me). 9.6/4 says very plainly:

"If the value of an enumerator is stored into a bitfield of the same
enumeration type and the number of bits in the bitfield is large enough to
hold all the values of that enumeration type, the original enumerator value
and the value of the bitfield shall compare equal."

I don't have a VS 2005 installation handy to test this - if it's still
broken there, go ahead and open a bug report for it.

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top