Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #9776 > unrolled thread
| Started by | Quentin Pope <qp19433@hotmail.NOSPAM.com> |
|---|---|
| First post | 2011-08-31 21:23 +0000 |
| Last post | 2011-09-01 16:27 -0700 |
| Articles | 11 on this page of 31 — 17 participants |
Back to article view | Back to comp.lang.c
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 2 of 2 — ← Prev page 1 [2]
| From | Phil Carmody <thefatphil_demunged@yahoo.co.uk> |
|---|---|
| Date | 2011-09-01 15:34 +0300 |
| Message-ID | <8762lca1bl.fsf@bazspaz.fatphil.org> |
| In reply to | #9782 |
Seebs <usenet-nospam@seebs.net> writes: > 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. The second thing wasn't a bitfield, it was a union. I would have been very surprised if the size hadn't been at least 8. On something like a Cray, I'd not have blinked if it had been 16 bytes. (Keith - you've used a Cray most recently, I think - can you shed any light on that?) Phil -- "Religion is what keeps the poor from murdering the rich." -- Napoleon
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-09-01 07:24 -0700 |
| Message-ID | <ln1uw0tk73.fsf@nuthaus.mib.org> |
| In reply to | #9808 |
Phil Carmody <thefatphil_demunged@yahoo.co.uk> writes:
> Seebs <usenet-nospam@seebs.net> writes:
>> 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.
>
> The second thing wasn't a bitfield, it was a union.
>
> I would have been very surprised if the size hadn't been at least 8.
> On something like a Cray, I'd not have blinked if it had been 16 bytes.
> (Keith - you've used a Cray most recently, I think - can you shed any
> light on that?)
Not on bit fields, sorry.
--
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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-08-31 17:55 -0400 |
| Message-ID | <4E5EADE5.6010701@verizon.net> |
| In reply to | #9776 |
On 08/31/2011 05:23 PM, 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.
>
>
> 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;
> };
Ian has already pointed out to you the syntax errors in that declaration.
> };
"An implementation may allocate any addressable storage unit large
enough to hold a bit-field. 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." (6.7.2.1p10)
However, the thing that follows proto is not another bit field, but a
union. The union contains two structs, both structs contain bit fields,
but those bit fields are not members of the same struct that proto is.
Therefore, 6.7.2.1p10 does not apply.
Here's an alternative approach that should cause the fields to be merged
into the same storage unit. However, there's no guarantees about what
size the "storage unit" is. It could have a size of 8.
struct s_skip_ind {
unsigned proto:4;
unsigned skip_ind:4;
};
struct s_trans_id {
unsigned proto:4;
unsigned trans_val:3;
unsigned trans_id:1;
};
union foo {
struct s_skip_ind skip_ind;
struct s_trans_id trans_id;
};
Note that, with this definition, both 'proto's are required to occupy
the same bits (6.5.2.3p5).
[toc] | [prev] | [next] | [standalone]
| From | "Scott Fluhrer" <sfluhrer@ix.netcom.com> |
|---|---|
| Date | 2011-08-31 19:01 -0400 |
| Message-ID | <1314831715.648791@rcdn-nntpcache-2> |
| In reply to | #9776 |
"Quentin Pope" <qp19433@hotmail.NOSPAM.com> wrote in message
news: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.
Actually, I don't think that the compiler is allowed to coalesce them. You
made skip_ind and trans_id structures, which means that you are allowed to
have pointers to them, as in:
struct foo example;
struct s_skip_id *p = &example.skip_ind;
You may have no intention of doing so, but the compiler doesn't know that.
Because all pointers must be on byte boundaries, this means that these
structures must be placed on byte boundaries.
>
>
> 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] | [prev] | [next] | [standalone]
| From | Peter Nilsson <airia@acay.com.au> |
|---|---|
| Date | 2011-08-31 16:03 -0700 |
| Message-ID | <610e0e48-76c6-476b-8303-2c0055781cdc@s35g2000prm.googlegroups.com> |
| In reply to | #9776 |
Quentin Pope <qp19...@hotmail.NOSPAM.com> wrote:
> On my compiler, the output of "sizeof(foo)" of the following
> is 8, instead of 4.
Did your compiler issue the required diagnostic?
> 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.
Depends whether you're using a conforming C compiler or not.
> 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;
C doesn't act like C++ when it comes to struct tags.
> };
C doesn't allow unnamed members in structs and unions, with the
exception of zero width bit-fields.
> };
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.
See James Kuyper's response for an alternative method.
--
Peter
[toc] | [prev] | [next] | [standalone]
| From | David Thompson <dave.thompson2@verizon.net> |
|---|---|
| Date | 2011-09-06 01:13 -0400 |
| Message-ID | <gvab67hq7evufs0upu3aliat65c14bofqu@4ax.com> |
| In reply to | #9787 |
On Wed, 31 Aug 2011 16:03:14 -0700 (PDT), Peter Nilsson
<airia@acay.com.au> 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.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-01-24 12:17 -0800 |
| Message-ID | <kfnhazkhn3h.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #9959 |
David Thompson <dave.thompson2@verizon.net> 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.
[toc] | [prev] | [next] | [standalone]
| From | ec429 <ec429@cam.ac.uk> |
|---|---|
| Date | 2012-01-25 00:13 +0000 |
| Message-ID | <jfnhg7$ahl$1@dont-email.me> |
| In reply to | #16114 |
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
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2012-01-25 00:36 +0000 |
| Message-ID | <20120124163119.715@kylheku.com> |
| In reply to | #16144 |
On 2012-01-25, ec429 <ec429@cam.ac.uk> 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.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-01-31 14:54 -0800 |
| Message-ID | <kfnty3b1o15.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #16144 |
ec429 <ec429@cam.ac.uk> 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.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2011-09-01 16:27 -0700 |
| Message-ID | <j3p4cs$5a2$1@dont-email.me> |
| In reply to | #9776 |
On 8/31/2011 2:23 PM, 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.
>
> 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;
> };
> };
No. You are making invalid conclusions from translating invalid code.
C language does not allow anonymous union members in the struct
declaration. Your declaration of `struct foo` is invalid C. If your
compiler accepted this declaration, it is a mere compiler-specific
extension, which has nothing to do with standard C language.
In C language you are required to give that union member an explicit
name, as in
struct foo {
unsigned proto:4;
union {
s_skip_ind skip_ind;
s_trans_id trans_id;
} u; /* <- the name is required */
};
Now note that the above member `u` should have its own offset and its
own address within `struct foo`, since at any place in your code you can
something like
struct foo f;
void *p = &f.u;
For this reason, the compiler simply cannot merge this union member with
the previous bit-field. It has too align `u` at the beginning of an
addressable memory unit.
Apparently your compiler was forgiving enough to let you (illegally)
omit the member name, but wasn't brave enough to take the next step and
do the merging.
In any case, if there is any compiler bug here, it is the failure of the
compiler to report the illegal anonymous union member, not the failure
to merge the bit-fields.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c
csiph-web