Bit-fields and packing/alignment

  • Thread starter =?iso-8859-1?q?Lars_Rune_N=F8stdal?=
  • Start date
?

=?iso-8859-1?q?Lars_Rune_N=F8stdal?=

struct X {
unsigned int a : 1;
unsigned int b : 1;
};

int main()
{
X* x = new X;
x->a = 1;
x->b = 1;
return(0);
}


Will this code not result in the two bits 'a' and 'b', both with the value
1, following each other (packed/aligned) in memory?

Like this, where the content between [ and ] represents a single bit in
memory: ..[1][1]..

From TC++PL. (§C8.1): "..using (bit)fields to pack several variables into
a byte.."

I assume a byte (or allocation unit, or word) on any platform known to man
has room for at least two bits, and therefore will not straddle.

From http://www.parashift.com/c++-faq-lite/intrinsic-types.html: "The C++
language guarantees a byte must always have at least 8 bits."

From the C++ standard (2003) (§9.6): "Bit fields are packed into some
addressable allocation unit."

Note that I'm not taking into account the details about stuff like MSB or
the actual size of what's allocated and possibly padded, or ignored as a
value here. What I want to know is if it's guaranteed that 'a' and 'b' is
packed/aligned here.

This is the output of the GDB under Linux (x86) when examining the
contents of 'x':


14 x->a = 1;
(gdb) x x
0x804a050: 00000000000000000000000000000000
(gdb) step
15 x->b = 1;
(gdb) x x
0x804a050: 00000000000000000000000000000001
(gdb) step
16 return(0);
(gdb) x x
0x804a050: 00000000000000000000000000000011
(gdb)

Sorry if the question is wierd -- but we're having quite a discussion
about this and I need to be 100% sure about how this works (and doesn't
work).
 
G

Gernot Frisch

Lars Rune Nøstdal said:
struct X {
unsigned int a : 1;
unsigned int b : 1;
};

int main()
{
X* x = new X;
x->a = 1;
x->b = 1;
return(0);
}


Will this code not result in the two bits 'a' and 'b', both with the value
1, following each other (packed/aligned) in memory?

STOP. You defined x.a and x.b as 'int'. and 'int' means: the buswidth
of your processor. On a 32 bit processor, this will be 32 bits.
Like this, where the content between [ and ] represents a single bit in
memory: ..[1][1]..

Either you got something really wrong here, or I don't know what you
want to say...
From TC++PL. (§C8.1): "..using (bit)fields to pack several variables into
a byte.."

Yes.

unsigned char a_byte;

a_byte = 0; // 00000000

a_byte |= 5; // 00000101
a_byte |= 2; // 00000111

I assume a byte (or allocation unit, or word) on any platform known to man
has room for at least two bits, and therefore will not straddle.

Ouch! A BYTE is defined as 8 BIT, a WORD as 2 BYTE (thus 16 BIT).
Both are graeter than 2 BITS, thus, yes you can store 2 bits:

From http://www.parashift.com/c++-faq-lite/intrinsic-types.html: "The C++
language guarantees a byte must always have at least 8 bits."
True.

From the C++ standard (2003) (§9.6): "Bit fields are packed into some
addressable allocation unit."
True

Note that I'm not taking into account the details about stuff like MSB or
the actual size of what's allocated and possibly padded, or ignored as a
value here. What I want to know is if it's guaranteed that 'a' and 'b' is
packed/aligned here.

Yes, it's guaranteed. x.a (32 bits!?) then following x.b (32 bits)
This is the output of the GDB under Linux (x86) when examining the
contents of 'x':


14 x->a = 1;
(gdb) x x
0x804a050: 00000000000000000000000000000000
(gdb) step
15 x->b = 1;
(gdb) x x
0x804a050: 00000000000000000000000000000001
(gdb) step
16 return(0);
(gdb) x x
0x804a050: 00000000000000000000000000000011
(gdb)

I don't know about gdb, but it seems weired...
 
R

Rob Williscroft

Lars Rune Nøstdal wrote in
in comp.lang.c++:
struct X {
unsigned int a : 1;
unsigned int b : 1;
};

int main()
{
X* x = new X;
x->a = 1;
x->b = 1;
return(0);
}


Will this code not result in the two bits 'a' and 'b', both with the
value 1, following each other (packed/aligned) in memory?

The Standard say's such things are implementation defined.
Like this, where the content between [ and ] represents a single bit
in memory: ..[1][1]..

Most machines don't have *bit* addressable memory, so the consept of
one bit following another in memory is fundamentaly flawed.
From TC++PL. (§C8.1): "..using (bit)fields to pack several variables
into a byte.."

I assume a byte (or allocation unit, or word) on any platform known to
man has room for at least two bits, and therefore will not straddle.

Its a resanable assupmtion, in C++ a "byte" (aka char) has at least
8 bits of object/value representation, however "reason" (aka logic)
doesn't apply here, the Standard says that how bit-fields are allocated
is implementation defined. If you *need* to know, you have to read the
documentation for the compiler your using.
From http://www.parashift.com/c++-faq-lite/intrinsic-types.html: "The
C++ language guarantees a byte must always have at least 8 bits."

From the C++ standard (2003) (§9.6): "Bit fields are packed into some
addressable allocation unit."

Note that I'm not taking into account the details about stuff like MSB
or the actual size of what's allocated and possibly padded, or ignored
as a value here. What I want to know is if it's guaranteed that 'a'
and 'b' is packed/aligned here.

No. But it may be (and probably is) guaranteed by you implementation
(aka compiler), read you docs'.

[snip]
Sorry if the question is wierd -- but we're having quite a discussion
about this and I need to be 100% sure about how this works (and
doesn't work).

If you need your "bits" to be stored in specific bits of a larger
object, you should store them in the larger object, and use the
<<, >>, & and | operators to manipulate the value bits of this object.

The only reasonable use of bitfields in portable code is to save
some memory when you know the value of a field is storeable in
a specific number of bits.

Rob.
 
J

Jack Klein

STOP. You defined x.a and x.b as 'int'. and 'int' means: the buswidth
of your processor. On a 32 bit processor, this will be 32 bits.

Do you have any idea at all what bit-fields are in C and C++?
Apparently not. x.a and x.b will indeed each contain 1 bit.
Like this, where the content between [ and ] represents a single bit in
memory: ..[1][1]..

Either you got something really wrong here, or I don't know what you
want to say...

No, what he has is perfectly correct.
Yes.

unsigned char a_byte;

a_byte = 0; // 00000000

a_byte |= 5; // 00000101
a_byte |= 2; // 00000111



Ouch! A BYTE is defined as 8 BIT, a WORD as 2 BYTE (thus 16 BIT).

Wrong again. There is no such thing as a 'BYTE' in the C++ language.
There is something called a 'byte'. Here is how the C++ language
standard defines a byte:

"The fundamental storage unit in the C++ memory model is the byte. A
byte is at least large enough to contain any member of the basic
execution character set and is composed of a contiguous sequence of
bits, the number of which is implementation-defined. The least
significant bit is called the low-order bit; the most significant bit
is called the high-order bit. The memory available to a C++ program
consists of one or more sequences of contiguous bytes. Every byte has
a unique address."

The standard requires that a byte contain at least 8 bits, it may
contain more. On some C++ implementations bytes contain 16 or 32
bits.

On the other hand, the language does not define a 'WORD' or a 'word',
nor does it require or guarantee that any data type is either 2 bytes
or 16 bits.
Both are graeter than 2 BITS, thus, yes you can store 2 bits:



Yes, it's guaranteed. x.a (32 bits!?) then following x.b (32 bits)

Obviously you should not respond to a post about bit-fields when you
do not understand them.
I don't know about gdb, but it seems weired...

No, it is perfectly reasonable.
 

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

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top