Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Bitfields in struct

Reply
Thread Tools

Bitfields in struct

 
 
Jason Curl
Guest
Posts: n/a
 
      10-11-2005
Hello C Group,

From what I remember, it is implementation dependent the way that a
compiler may order bitfields in a struct. In the example program I give,
Solaris Sparc gives one result, Intel x86 gives another result (for the
GCC compiler).

Is there a portable way to test how this information is stored? In
particular, will the result of the program below always result in c
being 0x01 or 0x80? Does the compiler allow for padding so that the
result may also be 0x00?

For example:

#include <stdio.h>

struct bitfield {
int b7:1;
int b6:1;
int b5:1;
int b4:1;
int b3:1;
int b2:1;
int b1:1;
int b0:1;
};

union highlow {
struct bitfield bf;
unsigned char c;
};

int main(void)
{
union highlow h;

h.c = 0;
h.bf.b0 = 1;

if (h.c == 0x80) {
printf("LSB machine\n");
} else {
printf("MSB machine\n");
}
printf("c = %02x\n", h.c);
}

--
Jason.
 
Reply With Quote
 
 
 
 
Jack Klein
Guest
Posts: n/a
 
      10-12-2005
On Tue, 11 Oct 2005 13:21:00 +0200, Jason Curl
<(E-Mail Removed)> wrote in comp.lang.c:

> Hello C Group,
>
> From what I remember, it is implementation dependent the way that a
> compiler may order bitfields in a struct. In the example program I give,
> Solaris Sparc gives one result, Intel x86 gives another result (for the
> GCC compiler).
>
> Is there a portable way to test how this information is stored? In
> particular, will the result of the program below always result in c
> being 0x01 or 0x80? Does the compiler allow for padding so that the
> result may also be 0x00?


The result might be 0x01. It might even be 0x80, but that is rather
unlikely.

> For example:
>
> #include <stdio.h>
>
> struct bitfield {
> int b7:1;


Note that when used to define bit-field members, plain 'int' is not
necessarily signed int. It may be unsigned int, that is
implementation defined.

Also note that a one-bit signed bit-field is dicey. It can have two
values, but are they 0 and 1 or 0 and -1? Frankly the C standard
leaves this ambiguous, and the behavior of compilers varies.

For single bit bit-fields, it is safest to explicitly used unsigned
int, or, if you have a C99 conforming compiler, _Bool which is an
unsigned integer type.

> int b6:1;
> int b5:1;
> int b4:1;
> int b3:1;
> int b2:1;
> int b1:1;
> int b0:1;
> };


You seem to assume that this bit-field will occupy exactly 8 bits. No
such requirement or guarantee exists in the C standard. There are
some platforms that will use a whole int or larger type, 16 or 32 or
more bits, not just 8.

> union highlow {
> struct bitfield bf;
> unsigned char c;
> };
>
> int main(void)
> {
> union highlow h;
>
> h.c = 0;
> h.bf.b0 = 1;
>
> if (h.c == 0x80) {
> printf("LSB machine\n");
> } else {
> printf("MSB machine\n");
> }
> printf("c = %02x\n", h.c);
> }


Do you actually mean "LSb" and "MSb", that is least and most
significant bit?

Padding has nothing to do with it. Assume an implementation that will
use an int to store the bit-field struct, which is not at all unusual.
So the underlying int has, for example, 32 bits. It is
implementation-defined whether bit-fields are allocated starting with
the most significant or least significant bit, but assume a
little-endian architecture with CHAR_BIT 8 that starts allocating from
the most significant bit.

In that case, the representation of the bit-field interpreted as an
unsigned 32 bit int would be 0x80000000, and it would appear in
memory, from lowest to highest address as 0x00, 0x00, 0x00, 0x80.

Now suppose a bit-endian implementation that starts allocating
bit-fields from the least significant bit. In that case, the
representation of the unsigned bit-field interpreted as a 32-bit
unsigned int would be 0x00000001, and it would appear in memory as
0x00, 0x00, 0x00, 0x01.

You are assuming that because you define a bit-field struct containing
8 bits, and you overlay an unsigned char over its first byte (and you
assume that your char has exactly 8 bits), that all of the 8 bits in
the bit-field will lie within that 8-bit char. There is no guarantee
of that at all.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
 
 
 
Jason Curl
Guest
Posts: n/a
 
      10-12-2005
Jack Klein wrote:
> On Tue, 11 Oct 2005 13:21:00 +0200, Jason Curl
> <(E-Mail Removed)> wrote in comp.lang.c:
>
>> Is there a portable way to test how this information is stored? In
>> particular, will the result of the program below always result in c
>> being 0x01 or 0x80? Does the compiler allow for padding so that the
>> result may also be 0x00?

>
> The result might be 0x01. It might even be 0x80, but that is rather
> unlikely.
>
>> For example:
>>
>> #include <stdio.h>
>>
>> struct bitfield {
>> int b7:1;

>
> Note that when used to define bit-field members, plain 'int' is not
> necessarily signed int. It may be unsigned int, that is
> implementation defined.
>
> Also note that a one-bit signed bit-field is dicey. It can have two
> values, but are they 0 and 1 or 0 and -1? Frankly the C standard
> leaves this ambiguous, and the behavior of compilers varies.
>
>> int b6:1;
>> int b5:1;
>> int b4:1;
>> int b3:1;
>> int b2:1;
>> int b1:1;
>> int b0:1;
>> };

>
> You seem to assume that this bit-field will occupy exactly 8 bits. No
> such requirement or guarantee exists in the C standard. There are
> some platforms that will use a whole int or larger type, 16 or 32 or
> more bits, not just 8.
>
>> union highlow {
>> struct bitfield bf;
>> unsigned char c;
>> };
>>
>> int main(void)
>> {
>> union highlow h;
>>
>> h.c = 0;
>> h.bf.b0 = 1;
>>
>> if (h.c == 0x80) {
>> printf("LSB machine\n");
>> } else {
>> printf("MSB machine\n");
>> }
>> printf("c = %02x\n", h.c);
>> }

>
> Do you actually mean "LSb" and "MSb", that is least and most
> significant bit?


Yes, LSb and MSb.

> Padding has nothing to do with it. Assume an implementation that will
> use an int to store the bit-field struct, which is not at all unusual.
> So the underlying int has, for example, 32 bits. It is
> implementation-defined whether bit-fields are allocated starting with
> the most significant or least significant bit, but assume a
> little-endian architecture with CHAR_BIT 8 that starts allocating from
> the most significant bit.
>
> In that case, the representation of the bit-field interpreted as an
> unsigned 32 bit int would be 0x80000000, and it would appear in
> memory, from lowest to highest address as 0x00, 0x00, 0x00, 0x80.
>
> Now suppose a bit-endian implementation that starts allocating
> bit-fields from the least significant bit. In that case, the
> representation of the unsigned bit-field interpreted as a 32-bit
> unsigned int would be 0x00000001, and it would appear in memory as
> 0x00, 0x00, 0x00, 0x01.


I'm assuming CHAR_BIT is 8, as required for POSIX. Must a conforming C
compiler must be consistent in how it allocates the bits?

For example, either 0x00000001, 0x80000000, 0x00008000 or 0x00000080 for
a 32-bit implementation. A 64-bit implementation would then possibly be
similar.

Or is this also in no way guaranteed by the C-standard? <ot> how about
these questions applied the posix standard? </ot>

>
> You are assuming that because you define a bit-field struct containing
> 8 bits, and you overlay an unsigned char over its first byte (and you
> assume that your char has exactly 8 bits), that all of the 8 bits in
> the bit-field will lie within that 8-bit char. There is no guarantee
> of that at all.
>


Rephrasing my question, does the C-standard specify (so that there are a
small number of limited possibilities) how two elements in a union overlay?

Thanks,
Jason.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
Packing a ctypes struct containing bitfields. Karthik Python 2 06-19-2009 05:51 AM
Questions on bitfields and struct sarathy C Programming 7 07-22-2006 06:06 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM
About very long Bit-numbers (bitfields?) Juha Kettunen C++ 9 04-10-2004 01:10 AM



Advertisments