Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #9776 > unrolled thread

Bit-field union bug

Started byQuentin Pope <qp19433@hotmail.NOSPAM.com>
First post2011-08-31 21:23 +0000
Last post2011-09-01 16:27 -0700
Articles 20 on this page of 31 — 17 participants

Back to article view | Back to comp.lang.c


Contents

  Bit-field union bug Quentin Pope <qp19433@hotmail.NOSPAM.com> - 2011-08-31 21:23 +0000
    Re: Bit-field union bug Keith Thompson <kst-u@mib.org> - 2011-08-31 14:34 -0700
      Re: Bit-field union bug Quentin Pope <qp19433@hotmail.NOSPAM.com> - 2011-09-03 19:06 +0000
        Re: Bit-field union bug Ian Collins <ian-news@hotmail.com> - 2011-09-04 08:19 +1200
          Re: Bit-field union bug Quentin Pope <qp19433@hotmail.NOSPAM.com> - 2011-09-03 21:12 +0000
            Re: Bit-field union bug Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-03 22:30 +0100
              Re: Bit-field union bug Ian Collins <ian-news@hotmail.com> - 2011-09-04 11:01 +1200
                Re: Bit-field union bug Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-04 00:37 +0100
                  Re: Bit-field union bug Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-09-06 00:36 +0300
              Re: Bit-field union bug Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 12:23 -0800
                Re: Bit-field union bug Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-01-24 21:15 +0000
    Re: Bit-field union bug Ian Collins <ian-news@hotmail.com> - 2011-09-01 09:36 +1200
    Re: Bit-field union bug jacob navia <jacob@spamsink.net> - 2011-08-31 23:38 +0200
    Re: Bit-field union bug Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-08-31 15:42 -0600
      Re: Bit-field union bug Seebs <usenet-nospam@seebs.net> - 2011-08-31 21:57 +0000
        Re: Bit-field union bug James Kuyper <jameskuyper@verizon.net> - 2011-08-31 18:21 -0400
          Re: Bit-field union bug Seebs <usenet-nospam@seebs.net> - 2011-09-01 02:45 +0000
            Re: Bit-field union bug James Kuyper <jameskuyper@verizon.net> - 2011-09-01 06:37 -0400
          Re: Bit-field union bug Kenneth Brody <kenbrody@spamcop.net> - 2011-09-01 14:19 -0400
            Re: Bit-field union bug James Kuyper <jameskuyper@verizon.net> - 2011-09-01 14:46 -0400
        Re: Bit-field union bug Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-09-01 15:34 +0300
          Re: Bit-field union bug Keith Thompson <kst-u@mib.org> - 2011-09-01 07:24 -0700
    Re: Bit-field union bug James Kuyper <jameskuyper@verizon.net> - 2011-08-31 17:55 -0400
    Re: Bit-field union bug "Scott Fluhrer" <sfluhrer@ix.netcom.com> - 2011-08-31 19:01 -0400
    Re: Bit-field union bug Peter Nilsson <airia@acay.com.au> - 2011-08-31 16:03 -0700
      Re: Bit-field union bug David Thompson <dave.thompson2@verizon.net> - 2011-09-06 01:13 -0400
        Re: Bit-field union bug Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 12:17 -0800
          Re: Bit-field union bug ec429 <ec429@cam.ac.uk> - 2012-01-25 00:13 +0000
            Re: Bit-field union bug Kaz Kylheku <kaz@kylheku.com> - 2012-01-25 00:36 +0000
            Re: Bit-field union bug Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-31 14:54 -0800
    Re: Bit-field union bug Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-09-01 16:27 -0700

Page 1 of 2  [1] 2  Next page →


#9776 — Bit-field union bug

FromQuentin Pope <qp19433@hotmail.NOSPAM.com>
Date2011-08-31 21:23 +0000
SubjectBit-field union bug
Message-ID<j3m8np$8gv$1@speranza.aioe.org>
On my compiler, the output of "sizeof(foo)" of the following is 8, 
instead of 4.

Which indicates that the compiler is aligning the union at
the next int boundary, rather than coalescing it with "proto".

I think this is a bug.


struct s_skip_ind {
   unsigned skip_ind:4;
};

struct s_trans_id {
   unsigned trans_val:3;
   unsigned trans_id:1;
};

struct foo {
   unsigned proto:4;
   union {
      s_skip_ind skip_ind;
      s_trans_id trans_id;
   };
};

[toc] | [next] | [standalone]


#9777

FromKeith Thompson <kst-u@mib.org>
Date2011-08-31 14:34 -0700
Message-ID<ln62ldtgdq.fsf@nuthaus.mib.org>
In reply to#9776
Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:
> On my compiler, the output of "sizeof(foo)" of the following is 8, 
> instead of 4.
>
> Which indicates that the compiler is aligning the union at
> the next int boundary, rather than coalescing it with "proto".
>
> I think this is a bug.
>
>
> struct s_skip_ind {
>    unsigned skip_ind:4;
> };
>
> struct s_trans_id {
>    unsigned trans_val:3;
>    unsigned trans_id:1;
> };
>
> struct foo {
>    unsigned proto:4;
>    union {
>       s_skip_ind skip_ind;
>       s_trans_id trans_id;
>    };
> };

Whether it's a bug or not, it's not a violation of the C standard.
Compilers can legally insert arbitrary padding between any two members
of a struct, or after the last one.

I think I've seen some compilers that use the declared type of a bit
field to determine its alignment; for example, given
    unsigned char  x:1
    unsigned short y:1
    unsigned int   z:1
x, y, and z might be aligned on 1-byte, 2-byte, and 4-byte boundaries,
respectively.  I don't think there's any support for this in the
standard, which only requires support for bit fields of types int,
signed int, unsigned int, and (new in C99) _Bool.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#9918

FromQuentin Pope <qp19433@hotmail.NOSPAM.com>
Date2011-09-03 19:06 +0000
Message-ID<j3ttr8$uil$1@speranza.aioe.org>
In reply to#9777
On Wed, 31 Aug 2011 14:34:09 -0700, Keith Thompson wrote:
> Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:
>> On my compiler, the output of "sizeof(foo)" of the following is 8,
>> instead of 4.
>>
>> Which indicates that the compiler is aligning the union at the next int
>> boundary, rather than coalescing it with "proto".
>>
>> I think this is a bug.
>>
>>
>> struct s_skip_ind {
>>    unsigned skip_ind:4;
>> };
>>
>> struct s_trans_id {
>>    unsigned trans_val:3;
>>    unsigned trans_id:1;
>> };
>>
>> struct foo {
>>    unsigned proto:4;
>>    union {
>>       s_skip_ind skip_ind;
>>       s_trans_id trans_id;
>>    };
>> };
> 
> Whether it's a bug or not, it's not a violation of the C standard.
> Compilers can legally insert arbitrary padding between any two members
> of a struct, or after the last one.
> 
> I think I've seen some compilers that use the declared type of a bit
> field to determine its alignment; for example, given
>     unsigned char  x:1
>     unsigned short y:1
>     unsigned int   z:1
> x, y, and z might be aligned on 1-byte, 2-byte, and 4-byte boundaries,
> respectively.  I don't think there's any support for this in the
> standard, which only requires support for bit fields of types int,
> signed int, unsigned int, and (new in C99) _Bool.

I see.

In this case, is there an equivalent of the offsetOf() function for 
bitfield members, to allow programmers to determine whether or not 
bitfields have been packed?

Cheers
QP

[toc] | [prev] | [next] | [standalone]


#9919

FromIan Collins <ian-news@hotmail.com>
Date2011-09-04 08:19 +1200
Message-ID<9cfgfeFsstU3@mid.individual.net>
In reply to#9918
On 09/ 4/11 07:06 AM, Quentin Pope wrote:
> On Wed, 31 Aug 2011 14:34:09 -0700, Keith Thompson wrote:
>> Quentin Pope<qp19433@hotmail.NOSPAM.com>  writes:
>>> On my compiler, the output of "sizeof(foo)" of the following is 8,
>>> instead of 4.
>>>
>>> Which indicates that the compiler is aligning the union at the next int
>>> boundary, rather than coalescing it with "proto".
>>
>> Whether it's a bug or not, it's not a violation of the C standard.
>> Compilers can legally insert arbitrary padding between any two members
>> of a struct, or after the last one.
>>
>> I think I've seen some compilers that use the declared type of a bit
>> field to determine its alignment; for example, given
>>      unsigned char  x:1
>>      unsigned short y:1
>>      unsigned int   z:1
>> x, y, and z might be aligned on 1-byte, 2-byte, and 4-byte boundaries,
>> respectively.  I don't think there's any support for this in the
>> standard, which only requires support for bit fields of types int,
>> signed int, unsigned int, and (new in C99) _Bool.
>
> I see.
>
> In this case, is there an equivalent of the offsetOf() function for
> bitfield members, to allow programmers to determine whether or not
> bitfields have been packed?

Won't the sizeof operator tell you?

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#9920

FromQuentin Pope <qp19433@hotmail.NOSPAM.com>
Date2011-09-03 21:12 +0000
Message-ID<j3u573$h5b$1@speranza.aioe.org>
In reply to#9919
On Sun, 04 Sep 2011 08:19:58 +1200, Ian Collins wrote:
> On 09/ 4/11 07:06 AM, Quentin Pope wrote:
>> On Wed, 31 Aug 2011 14:34:09 -0700, Keith Thompson wrote:
>>> Quentin Pope<qp19433@hotmail.NOSPAM.com>  writes:
>>>> On my compiler, the output of "sizeof(foo)" of the following is 8,
>>>> instead of 4.
>>>>
>>>> Which indicates that the compiler is aligning the union at the next
>>>> int boundary, rather than coalescing it with "proto".
>>>
>>> Whether it's a bug or not, it's not a violation of the C standard.
>>> Compilers can legally insert arbitrary padding between any two members
>>> of a struct, or after the last one.
>>>
>>> I think I've seen some compilers that use the declared type of a bit
>>> field to determine its alignment; for example, given
>>>      unsigned char  x:1
>>>      unsigned short y:1
>>>      unsigned int   z:1
>>> x, y, and z might be aligned on 1-byte, 2-byte, and 4-byte boundaries,
>>> respectively.  I don't think there's any support for this in the
>>> standard, which only requires support for bit fields of types int,
>>> signed int, unsigned int, and (new in C99) _Bool.
>>
>> I see.
>>
>> In this case, is there an equivalent of the offsetOf() function for
>> bitfield members, to allow programmers to determine whether or not
>> bitfields have been packed?
> 
> Won't the sizeof operator tell you?

Not necessarily I don't think.

For example, imagine
struct foo {
  unsigned short a:2;
  unsigned short b:2;
  unsigned short c:2;
  unsigned short d:2;
};

If sizeOf(foo) is 3, then there is no way of telling whether a and b are 
packed into 1 byte, or if it's b and c, or if it's c and d.

Cheers,
QP

[toc] | [prev] | [next] | [standalone]


#9921

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-09-03 22:30 +0100
Message-ID<0.d9fab49de2f78c213571.20110903223032BST.87zkil5n5z.fsf@bsb.me.uk>
In reply to#9920
Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:

> On Sun, 04 Sep 2011 08:19:58 +1200, Ian Collins wrote:
>> On 09/ 4/11 07:06 AM, Quentin Pope wrote:
>>> On Wed, 31 Aug 2011 14:34:09 -0700, Keith Thompson wrote:
>>>> Quentin Pope<qp19433@hotmail.NOSPAM.com>  writes:
>>>>> On my compiler, the output of "sizeof(foo)" of the following is 8,
>>>>> instead of 4.
>>>>>
>>>>> Which indicates that the compiler is aligning the union at the next
>>>>> int boundary, rather than coalescing it with "proto".
>>>>
>>>> Whether it's a bug or not, it's not a violation of the C standard.
>>>> Compilers can legally insert arbitrary padding between any two members
>>>> of a struct, or after the last one.
>>>>
>>>> I think I've seen some compilers that use the declared type of a bit
>>>> field to determine its alignment; for example, given
>>>>      unsigned char  x:1
>>>>      unsigned short y:1
>>>>      unsigned int   z:1
>>>> x, y, and z might be aligned on 1-byte, 2-byte, and 4-byte boundaries,
>>>> respectively.  I don't think there's any support for this in the
>>>> standard, which only requires support for bit fields of types int,
>>>> signed int, unsigned int, and (new in C99) _Bool.
>>>
>>> I see.
>>>
>>> In this case, is there an equivalent of the offsetOf() function for
>>> bitfield members, to allow programmers to determine whether or not
>>> bitfields have been packed?
>> 
>> Won't the sizeof operator tell you?
>
> Not necessarily I don't think.
>
> For example, imagine
> struct foo {
>   unsigned short a:2;
>   unsigned short b:2;
>   unsigned short c:2;
>   unsigned short d:2;
> };
>
> If sizeOf(foo) is 3, then there is no way of telling whether a and b are 
> packed into 1 byte, or if it's b and c, or if it's c and d.

Your point is valid but the example is not a good one.  First, by using
unsigned short you've gone outside of standard C -- anything is
possible.  If you were to replace short with int, then you would get
much more than think you might think you do:

In the "unsigned int" version, the C standard says that a, b, c and d
must be packed together, consecutively, in the first byte of the struct.
The "addressable storage unit" into which they get packed can't be less
than 1 byte in size and a byte can't be less than 8 bits wide.  Which
one goes in the high-significance position is not specified but it is
must be either a or d and the other must follow in order.

However, I think it is often the case that code that needs to know how
bit fields are packed is using them beyond their natural purpose.
Shifting and masking gives you far more control over how things pack and
is usually the way to go when it matters.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#9922

FromIan Collins <ian-news@hotmail.com>
Date2011-09-04 11:01 +1200
Message-ID<9cfpu1FsstU4@mid.individual.net>
In reply to#9921
On 09/ 4/11 09:30 AM, Ben Bacarisse wrote:
>
> However, I think it is often the case that code that needs to know how
> bit fields are packed is using them beyond their natural purpose.
> Shifting and masking gives you far more control over how things pack and
> is usually the way to go when it matters.

Or the code is written based on knowledge of the compiler being used.  I 
have often used bit fields to map hardware registers or bits in messages 
headers.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#9923

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-09-04 00:37 +0100
Message-ID<0.fa7feb432434a3a5f022.20110904003740BST.87ty8t5ha3.fsf@bsb.me.uk>
In reply to#9922
Ian Collins <ian-news@hotmail.com> writes:

> On 09/ 4/11 09:30 AM, Ben Bacarisse wrote:
>>
>> However, I think it is often the case that code that needs to know how
>> bit fields are packed is using them beyond their natural purpose.
>> Shifting and masking gives you far more control over how things pack and
>> is usually the way to go when it matters.
>
> Or the code is written based on knowledge of the compiler being used.
> I have often used bit fields to map hardware registers or bits in
> messages headers.

Absolutely.  Hence "often" and "usually".  If you can rely on the
compiler maintaining the layout you need there is no problem.  None the
less, bit fields seem to have a fascination for people learning C that
makes them dangerously seductive.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#9957

FromPhil Carmody <thefatphil_demunged@yahoo.co.uk>
Date2011-09-06 00:36 +0300
Message-ID<87pqje658m.fsf@bazspaz.fatphil.org>
In reply to#9923
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Ian Collins <ian-news@hotmail.com> writes:
> 
> > On 09/ 4/11 09:30 AM, Ben Bacarisse wrote:
> >>
> >> However, I think it is often the case that code that needs to know how
> >> bit fields are packed is using them beyond their natural purpose.
> >> Shifting and masking gives you far more control over how things pack and
> >> is usually the way to go when it matters.
> >
> > Or the code is written based on knowledge of the compiler being used.
> > I have often used bit fields to map hardware registers or bits in
> > messages headers.
> 
> Absolutely.  Hence "often" and "usually".  If you can rely on the
> compiler maintaining the layout you need there is no problem. 

This warning reminds me of the lack of trust I can have in that
every day:

In file included from drivers/input/touchscreen/atmel_mxt.c:34:
drivers/input/touchscreen/atmel_mxt_objects.h:45: note: Offset of packed bit-field 'bit' has changed in GCC 4.4

I'm not sure why there's the incompatibility, it seems a strange 
thing to change.

Phil
-- 
"Religion is what keeps the poor from murdering the rich."
-- Napoleon

[toc] | [prev] | [next] | [standalone]


#16115

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-01-24 12:23 -0800
Message-ID<kfnd3a8hmt7.fsf@x-alumni2.alumni.caltech.edu>
In reply to#9921
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:
>
>> [snip]
>>
>> For example, imagine
>> struct foo {
>>   unsigned short a:2;
>>   unsigned short b:2;
>>   unsigned short c:2;
>>   unsigned short d:2;
>> };
>>
>> If sizeOf(foo) is 3, then there is no way of telling whether a and b are 
>> packed into 1 byte, or if it's b and c, or if it's c and d.
>
> [snip]
>
> In the "unsigned int" version, the C standard says that a, b, c and d
> must be packed together, consecutively, in the first byte of the struct.
> The "addressable storage unit" into which they get packed can't be less
> than 1 byte in size and a byte can't be less than 8 bits wide.  Which
> one goes in the high-significance position is not specified but it is
> must be either a or d and the other must follow in order.

AFAIK the Standard does not require them to be in the first
byte, just the first addressable unit.  For example, they
might be the low-order bits in a four byte unsigned int
on a machine that is "big endian", ie, they would be in
the fourth byte rather than the first.

[toc] | [prev] | [next] | [standalone]


#16124

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-01-24 21:15 +0000
Message-ID<0.e86b040363f11709b8a6.20120124211516GMT.87pqe8hkez.fsf@bsb.me.uk>
In reply to#16115
Tim Rentsch <txr@alumni.caltech.edu> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:
>>
>>> [snip]
>>>
>>> For example, imagine
>>> struct foo {
>>>   unsigned short a:2;
>>>   unsigned short b:2;
>>>   unsigned short c:2;
>>>   unsigned short d:2;
>>> };
>>>
>>> If sizeOf(foo) is 3, then there is no way of telling whether a and b are 
>>> packed into 1 byte, or if it's b and c, or if it's c and d.
>>
>> [snip]
>>
>> In the "unsigned int" version, the C standard says that a, b, c and d
>> must be packed together, consecutively, in the first byte of the struct.
>> The "addressable storage unit" into which they get packed can't be less
>> than 1 byte in size and a byte can't be less than 8 bits wide.  Which
>> one goes in the high-significance position is not specified but it is
>> must be either a or d and the other must follow in order.
>
> AFAIK the Standard does not require them to be in the first
> byte, just the first addressable unit.  For example, they
> might be the low-order bits in a four byte unsigned int
> on a machine that is "big endian", ie, they would be in
> the fourth byte rather than the first.

Yes, I think you are right.  They must be packed consecutively in the
storage unit chosen by the implementation but that need not be a byte.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#9778

FromIan Collins <ian-news@hotmail.com>
Date2011-09-01 09:36 +1200
Message-ID<9c7nrbF8n6U1@mid.individual.net>
In reply to#9776
On 09/ 1/11 09:23 AM, Quentin Pope wrote:
> On my compiler, the output of "sizeof(foo)" of the following is 8,
> instead of 4.
>
> Which indicates that the compiler is aligning the union at
> the next int boundary, rather than coalescing it with "proto".
>
> I think this is a bug.

I don't.  Each struct member has to be correctly aligned.  There is 
nothing in the standard that says adjacent bit field structs should be 
coalesced.

> struct s_skip_ind {
>     unsigned skip_ind:4;
> };
>
> struct s_trans_id {
>     unsigned trans_val:3;
>     unsigned trans_id:1;
> };
>
> struct foo {
>     unsigned proto:4;
>     union {
>        s_skip_ind skip_ind;

struct keyword missing.

>        s_trans_id trans_id;
>     };

Here you have an unnamed structure member, with is isn't standard, so 
the compiler could do what it likes, including ignoring it.

> };


-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#9779

Fromjacob navia <jacob@spamsink.net>
Date2011-08-31 23:38 +0200
Message-ID<j3m9ku$atp$1@speranza.aioe.org>
In reply to#9776
Le 31/08/11 23:23, Quentin Pope a écrit :
> On my compiler, the output of "sizeof(foo)" of the following is 8,
> instead of 4.
>
> Which indicates that the compiler is aligning the union at
> the next int boundary, rather than coalescing it with "proto".
>
> I think this is a bug.
>
>
> struct s_skip_ind {
>     unsigned skip_ind:4;
> };
>
> struct s_trans_id {
>     unsigned trans_val:3;
>     unsigned trans_id:1;
> };
>
> struct foo {
>     unsigned proto:4;
>     union {
>        s_skip_ind skip_ind;
>        s_trans_id trans_id;
>     };
> };

Most compilers have some option to control alignment.

#pragma pack(1) (For lcc-win or Microsoft coompilers)

__attribute__((packed)) (for gcc)

Read your compiler documentation on how to control the alignment.

[toc] | [prev] | [next] | [standalone]


#9780

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2011-08-31 15:42 -0600
Message-ID<1bbov5xnp5.fsf@snowball.wb.pfeifferfamily.net>
In reply to#9776
Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:

> On my compiler, the output of "sizeof(foo)" of the following is 8, 
> instead of 4.
>
> Which indicates that the compiler is aligning the union at
> the next int boundary, rather than coalescing it with "proto".
>
> I think this is a bug.
>
>
> struct s_skip_ind {
>    unsigned skip_ind:4;
> };
>
> struct s_trans_id {
>    unsigned trans_val:3;
>    unsigned trans_id:1;
> };
>
> struct foo {
>    unsigned proto:4;
>    union {
>       s_skip_ind skip_ind;
>       s_trans_id trans_id;
>    };
> };

While I would agree with you, the standard disagrees with both of us.
I'm not quite sure what the point of a bitfield is when the compiler is
free to insert arbitrary padding between elements, but that is indeed
the case.

[toc] | [prev] | [next] | [standalone]


#9782

FromSeebs <usenet-nospam@seebs.net>
Date2011-08-31 21:57 +0000
Message-ID<slrnj5tbae.sup.usenet-nospam@guild.seebs.net>
In reply to#9780
On 2011-08-31, Joe Pfeiffer <pfeiffer@cs.nmsu.edu> wrote:
> While I would agree with you, the standard disagrees with both of us.
> I'm not quite sure what the point of a bitfield is when the compiler is
> free to insert arbitrary padding between elements, but that is indeed
> the case.

The point is that the compiler is *permitted* to coalesce bitfields.  But
not required to, because some systems really don't provide meaningful support
for them.

Basically, bitfields aren't expected to provide an absolutely reliable
mapping onto a series of bits; they're expected to provide a way that you
can hint that you don't need a lot of storage, such that compilers can in
some cases save a few bytes.

-s
-- 
Copyright 2011, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

[toc] | [prev] | [next] | [standalone]


#9783

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-08-31 18:21 -0400
Message-ID<4E5EB3D5.9090402@verizon.net>
In reply to#9782
On 08/31/2011 05:57 PM, Seebs wrote:
> On 2011-08-31, Joe Pfeiffer <pfeiffer@cs.nmsu.edu> wrote:
>> While I would agree with you, the standard disagrees with both of us.
>> I'm not quite sure what the point of a bitfield is when the compiler is
>> free to insert arbitrary padding between elements, but that is indeed
>> the case.
> 
> The point is that the compiler is *permitted* to coalesce bitfields.  But
> not required to, because some systems really don't provide meaningful support
> for them.

Actually, it is required to do so, when adjacent bit-fields in the same
struct fit in a single storage unit (6.7.2.1p10). And since CHAR_BIT is
required to be >=8, these bit-fields, had they been in the same struct,
would have been required to be stored in adjacent bits of the same
storage unit.

> Basically, bitfields aren't expected to provide an absolutely reliable
> mapping onto a series of bits; they're expected to provide a way that you
> can hint that you don't need a lot of storage, such that compilers can in
> some cases save a few bytes.

An implementation has a lot of freedom to allocate bit-fields; far too
much to make any portable use of them for communications outside of a
single program. However, there's not quite as much freedom as you
thought there was.

[toc] | [prev] | [next] | [standalone]


#9793

FromSeebs <usenet-nospam@seebs.net>
Date2011-09-01 02:45 +0000
Message-ID<slrnj5tj2n.11vj.usenet-nospam@guild.seebs.net>
In reply to#9783
On 2011-08-31, James Kuyper <jameskuyper@verizon.net> wrote:
> Actually, it is required to do so, when adjacent bit-fields in the same
> struct fit in a single storage unit (6.7.2.1p10).

Thanks for the correction.  I had a vague sense that there were circumstances
where it was mandatory, and I hadn't thought through that the separate
struct declarations were the problem.

In fact, so far as I can tell, it's *not* permissible to coalesce adjacent
structs.

Assume CHAR_BIT is 8.

	struct a { int x:4; };
	struct b { struct a a1, a2; } example_b;

If struct b coalesced the bit fields, what would the address of example_b.a2
be?  The "struct a" object MUST have a size of at least 1, and it has to be
an integer size.

So you have to calculate the padding of the struct a independently, and then
use that padded object as the sub-member in other structs.

(I wonder whether that's true in Plan 9 C of anonymous structure members...)

-s
-- 
Copyright 2011, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

[toc] | [prev] | [next] | [standalone]


#9803

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-01 06:37 -0400
Message-ID<j3nn94$bbe$1@dont-email.me>
In reply to#9793
On 08/31/2011 10:45 PM, Seebs wrote:
> On 2011-08-31, James Kuyper <jameskuyper@verizon.net> wrote:
>> Actually, it is required to do so, when adjacent bit-fields in the same
>> struct fit in a single storage unit (6.7.2.1p10).
...
> In fact, so far as I can tell, it's *not* permissible to coalesce adjacent
> structs.

Of course. That was apparently not as obvious to the OP as it seems to me.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#9830

FromKenneth Brody <kenbrody@spamcop.net>
Date2011-09-01 14:19 -0400
Message-ID<XZudnYcMB5FbUcLTnZ2dnUVZ_v2dnZ2d@bestweb.net>
In reply to#9783
On 8/31/2011 6:21 PM, James Kuyper wrote:
> On 08/31/2011 05:57 PM, Seebs wrote:
>> On 2011-08-31, Joe Pfeiffer<pfeiffer@cs.nmsu.edu>  wrote:
>>> While I would agree with you, the standard disagrees with both of us.
>>> I'm not quite sure what the point of a bitfield is when the compiler is
>>> free to insert arbitrary padding between elements, but that is indeed
>>> the case.
>>
>> The point is that the compiler is *permitted* to coalesce bitfields.  But
>> not required to, because some systems really don't provide meaningful support
>> for them.
>
> Actually, it is required to do so, when adjacent bit-fields in the same
> struct fit in a single storage unit (6.7.2.1p10). And since CHAR_BIT is
> required to be>=8, these bit-fields, had they been in the same struct,
> would have been required to be stored in adjacent bits of the same
> storage unit.

But, this is not two bit-fields.  Here's the original code:

>> > struct s_skip_ind {
>> >    unsigned skip_ind:4;
>> > };
>> >
>> > struct s_trans_id {
>> >    unsigned trans_val:3;
>> >    unsigned trans_id:1;
>> > };
>> >
>> > struct foo {
>> >    unsigned proto:4;
>> >    union {
>> >       s_skip_ind skip_ind;
>> >       s_trans_id trans_id;
>> >    };
>> > };

The struct "foo" consists of a bit-field and a union.  The fact that the 
union consists of two structs which, in turn, consist of bit-fields, is 
irrelevant to 6.7.2.1p10 (as I read it):

> If enough space remains, a bit-field that immediately follows another
> bit-field in a structure shall be packed into adjacent bits of the same
> unit.

What follows the bit-field "proto" is an unnamed union, not another bit-field.


[...]
> An implementation has a lot of freedom to allocate bit-fields; far too
> much to make any portable use of them for communications outside of a
> single program. However, there's not quite as much freedom as you
> thought there was.

As I found out years ago when a bit-mapped flags value stored on disk was 
not portable to another system whose compiler allocated bit-fields the other 
way.

struct foo {
     ...
     struct {
         int SomeFlag:1;
         int AnotherFlag:1;
         }
         Flags;
     ...
     };

It's now just an "unsigned short" with an enum for bit-mask values.

-- 
Kenneth Brody

[toc] | [prev] | [next] | [standalone]


#9832

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-01 14:46 -0400
Message-ID<4E5FD30A.8000908@verizon.net>
In reply to#9830
On 09/01/2011 02:19 PM, Kenneth Brody wrote:
> On 8/31/2011 6:21 PM, James Kuyper wrote:
>> On 08/31/2011 05:57 PM, Seebs wrote:
>>> On 2011-08-31, Joe Pfeiffer<pfeiffer@cs.nmsu.edu>  wrote:
>>>> While I would agree with you, the standard disagrees with both of us.
>>>> I'm not quite sure what the point of a bitfield is when the compiler is
>>>> free to insert arbitrary padding between elements, but that is indeed
>>>> the case.
>>>
>>> The point is that the compiler is *permitted* to coalesce bitfields.  But
>>> not required to, because some systems really don't provide meaningful support
>>> for them.
>>
>> Actually, it is required to do so, when adjacent bit-fields in the same
>> struct fit in a single storage unit (6.7.2.1p10). And since CHAR_BIT is
>> required to be>=8, these bit-fields, had they been in the same struct,
>> would have been required to be stored in adjacent bits of the same
>> storage unit.
> 
> But, this is not two bit-fields.  Here's the original code:

I already raised that point in an earlier message. In this message I was
dealing with a different point.

In the case described by the OP, a compiler is prohibited from
coalescing "proto" with any of the other bit-fields, because if the
unnamed union member had been given a name (as it should have been),
that member would have been required to have a distinct address.

However, in the case which I was referring to above, "adjacent
bit-fields in the same struct", it's not merely permitted to coalesce
such bit-fields, it's required to do so, if it can.

Either way, "permitted" was an incorrect description.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web