Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Bit-field union bug

Reply
Thread Tools

Bit-field union bug

 
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-03-2011
Ian Collins <(E-Mail Removed)> 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.
 
Reply With Quote
 
 
 
 
Phil Carmody
Guest
Posts: n/a
 
      09-05-2011
Ben Bacarisse <(E-Mail Removed)> writes:
> Ian Collins <(E-Mail Removed)> 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
 
Reply With Quote
 
 
 
 
David Thompson
Guest
Posts: n/a
 
      09-06-2011
On Wed, 31 Aug 2011 16:03:14 -0700 (PDT), Peter Nilsson
<(E-Mail Removed)> wrote:

> If we replace this with...
>
> struct foo {
> unsigned proto:4;
> union {
> struct s_skip_ind skip_ind;
> struct s_trans_id trans_id;
> } u;
> };
>
> ...then you should realise that a conforming C compiler must be
> able to support the following...
>
> struct foo f;
> union {
> struct s_skip_ind skip_ind;
> struct s_trans_id trans_id;
> } *up = &f.u;
>
> It would make the compiler's life a tad difficult if it had to
> support that _and_ coalesce bit-fields in the way you would like.
>

Yes but no. Yes foo.u must be addressable preventing bit-field
packing. No you can't use &f.u that way.

<topic shift>
*Within a translation unit*, two declarations/definitions of struct or
union types with the same contents are *not* formally compatible
types. In practice a sane compiler will lay them out the same (unless
you alter something like #pragma pack) and so accesses will work if
you cast, but you need a tag or typedef to cast.

*Between translation units* if the tag, member names and types are the
same, it is completely compatible.

 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      01-24-2012
David Thompson <(E-Mail Removed)> writes:

> <topic shift>
> *Within a translation unit*, two declarations/definitions of struct or
> union types with the same contents are *not* formally compatible
> types. In practice a sane compiler will lay them out the same (unless
> you alter something like #pragma pack) and so accesses will work if
> you cast, but you need a tag or typedef to cast.


Identical layout is not enough to make things work in
the presence of type-sensitive optimization. In the
past one could generally get away with such things,
but that's becoming less true as time goes on.
 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      01-24-2012
Ben Bacarisse <(E-Mail Removed)> writes:

> Quentin Pope <(E-Mail Removed)> 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.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-24-2012
Tim Rentsch <(E-Mail Removed)> writes:

> Ben Bacarisse <(E-Mail Removed)> writes:
>
>> Quentin Pope <(E-Mail Removed)> 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.
 
Reply With Quote
 
ec429
Guest
Posts: n/a
 
      01-25-2012
On 24/01/12 20:17, Tim Rentsch wrote:
> Identical layout is not enough to make things work in
> the presence of type-sensitive optimization. In the
> past one could generally get away with such things,
> but that's becoming less true as time goes on.

Why is this? If the two struct (say) types have been defined
identically, what optimisation can the compiler possibly make that'll be
valid for one but not the other?
-e
--
'sane', adj.: see 'unimaginative'
on the web - http://jttlov.no-ip.org
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      01-25-2012
On 2012-01-25, ec429 <(E-Mail Removed)> wrote:
> On 24/01/12 20:17, Tim Rentsch wrote:
>> Identical layout is not enough to make things work in
>> the presence of type-sensitive optimization. In the
>> past one could generally get away with such things,
>> but that's becoming less true as time goes on.

> Why is this? If the two struct (say) types have been defined
> identically, what optimisation can the compiler possibly make that'll be
> valid for one but not the other?


It can assume that foo->x = 42 has no effect on the value of bar->x, continuing
to use a stale cached value, because foo and bar are pointers to different
declared structure types.
 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      01-31-2012
ec429 <(E-Mail Removed)> writes:

> On 24/01/12 20:17, Tim Rentsch wrote:
>> Identical layout is not enough to make things work in
>> the presence of type-sensitive optimization. In the
>> past one could generally get away with such things,
>> but that's becoming less true as time goes on.

>
> Why is this? If the two struct (say) types have been defined
> identically, what optimisation can the compiler possibly make that'll
> be valid for one but not the other?


What Kaz Kylheku said -- stores into one kind of struct can
be assumed not to affect members in a different kind of
struct, if the two structs involved are not both in a single
union object. Note that this latter condition can happen
even if both struct types are included in a union but one
of the actual struct objects is known not to be in a union.
For example, compiling (I haven't actually compiled this,
please excuse any minor mistakes):

struct foo { int x; ... };
struct bas { int x; ... };
union foobas { struct foo f; struct bas b; };
extern struct foo global_foo = { 1 };

int
mumble( union foobas *p, struct bas *q ){
global_foo.x = 7;

q->x = 13;
p->b.x = 14;
p->f.x = 15;

return global_foo.x;
}

the compiler is allowed to assume the function will return
the value 7, because none of the intermediate assignments
can affect global_foo.x. However, the three intermediate
assignments cannot be rearranged relative to each other,
because any one of them might affect the others.
 
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
*bug* *bug* *bug* David Raleigh Arnold Firefox 12 04-02-2007 03:13 AM
SQL UNION -like filtering of offline DataSet into DataView for WebControl binding Marco Ippolito ASP .Net 2 05-19-2004 12:35 AM
union in struct without union name Peter Dunker C Programming 2 04-26-2004 07:23 PM
map XML union to C union (and vice-versa) Matt Garman XML 1 04-25-2004 12:40 AM
THE STATE OF THE UNION Jenna Bush MCSE 95 01-30-2004 02:02 PM



Advertisments