Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #20303 > unrolled thread
| Started by | John Reye <jononanon@googlemail.com> |
|---|---|
| First post | 2012-05-03 10:04 -0700 |
| Last post | 2012-05-08 06:19 -0700 |
| Articles | 20 on this page of 57 — 12 participants |
Back to article view | Back to comp.lang.c
List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 10:04 -0700
Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 17:38 +0000
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 10:50 -0700
Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 11:09 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:18 -0700
Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 11:24 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:35 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:56 -0700
Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 12:16 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 12:20 -0700
Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 12:39 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 17:51 -0700
Re: List of undefined behaviour and other sneeky bugs "Joachim Schmitz" <nospam.jojo@schmitz-digital.de> - 2012-05-08 09:10 +0200
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 05:31 -0700
Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 18:11 +0000
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:29 -0700
Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 19:19 +0000
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 13:31 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 14:18 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 15:20 -0700
Re: List of undefined behaviour and other sneeky bugs Nobody <nobody@nowhere.com> - 2012-05-04 01:47 +0100
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 17:47 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 17:45 -0700
Re: List of undefined behaviour and other sneeky bugs nick_keighley_nospam@hotmail.com - 2012-05-08 00:43 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 06:17 -0700
Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 12:46 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 13:35 -0700
Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 14:05 -0700
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 14:11 -0700
Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 15:02 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:10 -0700
Re: List of undefined behaviour and other sneeky bugs nick_keighley_nospam@hotmail.com - 2012-05-08 00:49 -0700
Re: List of undefined behaviour and other sneeky bugs James Kuyper <jameskuyper@verizon.net> - 2012-05-08 06:37 -0400
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 07:49 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 07:25 -0700
Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-08 09:46 -0700
Re: List of undefined behaviour and other sneeky bugs James Kuyper <jameskuyper@verizon.net> - 2012-05-03 18:24 -0400
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:24 -0700
Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 21:17 +0000
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:28 -0700
Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 15:54 -0700
Re: List of undefined behaviour and other sneeky bugs Old Wolf <oldwolf@inspire.net.nz> - 2012-05-06 22:32 -0700
Re: List of undefined behaviour and other sneeky bugs Jens Gustedt <jens.gustedt@loria.fr> - 2012-05-07 08:26 +0200
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:31 -0700
Re: List of undefined behaviour and other sneeky bugs Jens Gustedt <jens.gustedt@loria.fr> - 2012-05-03 23:18 +0200
Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 15:58 -0700
Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-04 00:25 -0400
Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 22:28 -0700
Re: List of undefined behaviour and other sneeky bugs James Kuyper <jameskuyper@verizon.net> - 2012-05-04 07:33 -0400
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 19:20 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:50 -0700
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:42 -0700
Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-07 23:45 -0400
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 23:01 -0700
Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-08 06:28 -0400
Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-08 06:37 -0400
Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 06:19 -0700
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2012-05-04 01:47 +0100 |
| Message-ID | <pan.2012.05.04.00.47.07.390000@nowhere.com> |
| In reply to | #20330 |
On Thu, 03 May 2012 19:19:40 +0000, Jens Thoms Toerring wrote: >> Well yes, because there are machines with different endianness. > >> But I can get around that quite easy like this: >> #ifdef LITTLE_ENDIAN >> #else You forgot the "PDP-endian" case: 16-bit values are stored as low-byte followed by high-byte, while 32-bit values are stored as high-word followed by low-word (i.e. 0x01020304 is stored as 0x0102,0x0304 which is stored as 0x02,0x01,0x04,0x03). For a 4-byte value, there are 24 possible permutations, and a conforming implementation could use any of them.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 17:47 -0700 |
| Message-ID | <kfn4nrrzefb.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20309 |
John Reye <jononanon@googlemail.com> writes:
> Thanks for the warning about sizeof!! I missed that.
>
> On May 3, 7:38 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
>> > Or:
>> > struct
>> > {
>> > char a;
>> > union {
>> > int b;
>> > char c;
>> > };
>> > } mystruct;
>> > mystruct.c = 0x12
>> > Would this union work on every platform??
>>
>> Yes. But the you won't be able to use the 'b' element of
>> the union since reading a different member than has been
>> set the last time round also invokes undefined behavior.
>
> Oh no, please no. Why on earth would that be undefined behaviour?
> [snip]
It isn't. On platforms that have trap representations
it is possible for undefined behavior to arise, but
that's because of reading a trap representation, not
because of reading a union member other than the last
one set.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 17:45 -0700 |
| Message-ID | <kfn8vh3zejr.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20306 |
jt@toerring.de (Jens Thoms Toerring) writes:
> John Reye <jononanon@googlemail.com> wrote:
>[snip]
>> Or:
>> struct
>> {
>> char a;
>> union {
>> int b;
>> char c;
>> };
>> } mystruct;
>> mystruct.c = 0x12
>
>> Would this union work on every platform??
>
> Yes. But the you won't be able to use the 'b' element of
> the union since reading a different member than has been
> set the last time round also invokes undefined behavior.
That's wrong. Reading a member other than the last member
set has defined behavior. In cases where the member read
has a size larger than the last member set (as is the case
here), the value read depends on unspecified values in
some bytes. If those unspecified values cause the object
representation for the type in question to be a trap
representation, then that will cause undefined behavior.
But simply reading a member other than the last member
set is not in and of itself undefined behavior. And the
usual case, ie, reading a member whose size is no larger
than that of the member set, commonly has well-defined
and sometimes useful behavior.
[toc] | [prev] | [next] | [standalone]
| From | nick_keighley_nospam@hotmail.com |
|---|---|
| Date | 2012-05-08 00:43 -0700 |
| Message-ID | <28029579.3276.1336463009075.JavaMail.geo-discussion-forums@vbbgl4> |
| In reply to | #20477 |
On Tuesday, May 8, 2012 1:45:12 AM UTC+1, Tim Rentsch wrote:
> jt@toerring.de (Jens Thoms Toerring) writes:
>
> > John Reye <jononanon@googlemail.com> wrote:
> >[snip]
> >> Or:
> >> struct
> >> {
> >> char a;
> >> union {
> >> int b;
> >> char c;
> >> };
> >> } mystruct;
> >> mystruct.c = 0x12
> >
> >> Would this union work on every platform??
> >
> > Yes. But the you won't be able to use the 'b' element of
> > the union since reading a different member than has been
> > set the last time round also invokes undefined behavior.
>
> That's wrong. Reading a member other than the last member
> set has defined behavior. In cases where the member read
> has a size larger than the last member set (as is the case
> here), the value read depends on unspecified values in
> some bytes. If those unspecified values cause the object
> representation for the type in question to be a trap
> representation, then that will cause undefined behavior.
> But simply reading a member other than the last member
> set is not in and of itself undefined behavior. And the
> usual case, ie, reading a member whose size is no larger
> than that of the member set, commonly has well-defined
> and sometimes useful behavior.
but it is implementation defined so you can't, in general, predict what value you'll get
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-08 06:17 -0700 |
| Message-ID | <kfnk40mx15g.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20493 |
nick_keighley_nospam@hotmail.com writes:
> On Tuesday, May 8, 2012 1:45:12 AM UTC+1, Tim Rentsch wrote:
>> jt@toerring.de (Jens Thoms Toerring) writes:
>>
>> > John Reye <jononanon@googlemail.com> wrote:
>> >[snip]
>> >> Or:
>> >> struct
>> >> {
>> >> char a;
>> >> union {
>> >> int b;
>> >> char c;
>> >> };
>> >> } mystruct;
>> >> mystruct.c = 0x12
>> >
>> >> Would this union work on every platform??
>> >
>> > Yes. But the you won't be able to use the 'b' element of
>> > the union since reading a different member than has been
>> > set the last time round also invokes undefined behavior.
>>
>> That's wrong. Reading a member other than the last member
>> set has defined behavior. In cases where the member read
>> has a size larger than the last member set (as is the case
>> here), the value read depends on unspecified values in
>> some bytes. If those unspecified values cause the object
>> representation for the type in question to be a trap
>> representation, then that will cause undefined behavior.
>> But simply reading a member other than the last member
>> set is not in and of itself undefined behavior. And the
>> usual case, ie, reading a member whose size is no larger
>> than that of the member set, commonly has well-defined
>> and sometimes useful behavior.
>
> but it is implementation defined so you can't, in general,
> predict what value you'll get
Neither C11 nor C99 use 'implementation-defined' in the
description of union member access. The C90/C89 standard does
use this phrase; however, what was meant, and what was generally
understood by implementors, is that the result is defined (ie, as
reinterpreting the underlying bits in the new representation) but
depends on other implementation-defined choices, the most obvious
of which is how different types are represented. I suppose it is
possible, even though very unlikely, that some implementors of
very old compilers took advantage of the 'implementation-defined'
stipulation in C90 to do something unexpected here. Do you have
any experience that suggests such implementations actually exist?
Unless there is one such otherwise-conforming implementation that
someone can point to, I don't think it's wrong to say the behavior
is defined even under C90; certainly it is right under both C99
and the current C11 standard.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-05-03 12:46 -0700 |
| Message-ID | <lnobq5nj2o.fsf@nuthaus.mib.org> |
| In reply to | #20303 |
John Reye <jononanon@googlemail.com> writes:
[...]
> struct
> {
> char a;
> union {
> int b;
> char c;
> };
> } mystruct;
> mystruct.c = 0x12
>
> Would this union work on every platform??
You have an unnamed union. Some compilers support this as an extension,
but it's not valid in standard C.
You can fix it like this:
struct {
char a;
union {
int b;
char c;
} u;
} mystruct;
mystruct.u.c = 0x12;
Note that you have to refer to mystruct.u.c, not mystruct.c, since c is
a member of a union which is a member of a struct.
As for whether it "works", that depends on what you want it to do. It
stores the value 0x12 in mystruct.u.c, which is also the first byte of
mystruct.u.b. If you access the first byte of mystruct.u.b,
*(char*)&mystruct.u.b, you'll get 0x12. If you access mystruct.u.b as
an int, you'll get garbage, possibly a trap representation.
I can't think of anything useful you could do with this. If you want to
access the char value you just stored, you can refer to mystruct.u.c.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | John Reye <jononanon@googlemail.com> |
|---|---|
| Date | 2012-05-03 13:35 -0700 |
| Message-ID | <c42bba9a-5395-420a-abcb-5bdbc248e780@cl4g2000vbb.googlegroups.com> |
| In reply to | #20338 |
On May 3, 9:46 pm, Keith Thompson <ks...@mib.org> wrote: > As for whether it "works", that depends on what you want it to do. It > stores the value 0x12 in mystruct.u.c, which is also the first byte of > mystruct.u.b. If you access the first byte of mystruct.u.b, > *(char*)&mystruct.u.b, you'll get 0x12. If you access mystruct.u.b as > an int, you'll get garbage, possibly a trap representation. Will I really get garbage? I think not. The lowest-addressed byte is 0x12, and the other bytes of mystruct.u.b are what they were before, right? A trap? How can that possibly be justified? Why does the C language have unions then? What is the intended use of unions? Thanks
[toc] | [prev] | [next] | [standalone]
| From | Ben Pfaff <blp@cs.stanford.edu> |
|---|---|
| Date | 2012-05-03 14:05 -0700 |
| Message-ID | <87pqalnffh.fsf@blp.benpfaff.org> |
| In reply to | #20344 |
John Reye <jononanon@googlemail.com> writes:
> Why does the C language have unions then? What is the intended
> use of unions?
"Tagged" unions are useful for, among other purposes,
constructing trees in which different nodes may contain different
data.
enum node_type {
/* Terminal. */
INT,
REAL,
/* Nonterminal. */
ADD,
SUB,
MUL,
DIV
};
struct node {
enum node_type type;
union {
int integer; /* INT */
double real; /* REAL */
struct node *children[2]; /* ADD, SUB, MUL, DIV */
} u;
};
[toc] | [prev] | [next] | [standalone]
| From | John Reye <jononanon@googlemail.com> |
|---|---|
| Date | 2012-05-03 14:11 -0700 |
| Message-ID | <fc405a25-cfaf-4c4d-926d-1084ead31d34@n1g2000vby.googlegroups.com> |
| In reply to | #20349 |
On May 3, 11:05 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
> John Reye <jonona...@googlemail.com> writes:
> > Why does the C language have unions then? What is the intended
> > use of unions?
>
> "Tagged" unions are useful for, among other purposes,
> constructing trees in which different nodes may contain different
> data.
>
> enum node_type {
> /* Terminal. */
> INT,
> REAL,
>
> /* Nonterminal. */
> ADD,
> SUB,
> MUL,
> DIV
>
> };
>
> struct node {
> enum node_type type;
> union {
> int integer; /* INT */
> double real; /* REAL */
> struct node *children[2]; /* ADD, SUB, MUL, DIV */
> } u;
>
>
>
>
>
>
>
> };
So if you use a particular union access member... for a particular
union in memory, then you should always access that particular union-
variable, with the same member?
Is that the only intended use?
In particular: is it a misuse of unions, to use them in order to
enable different memory-accesses (word, byte, etc.) to the same
portion of memory???? I have (mis)used it like this in above posts
quite often.
Is that strictly wrong?
Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Ben Pfaff <blp@cs.stanford.edu> |
|---|---|
| Date | 2012-05-03 15:02 -0700 |
| Message-ID | <87havworda.fsf@blp.benpfaff.org> |
| In reply to | #20352 |
John Reye <jononanon@googlemail.com> writes: > On May 3, 11:05 pm, Ben Pfaff <b...@cs.stanford.edu> wrote: > So if you use a particular union access member... for a particular > union in memory, then you should always access that particular union- > variable, with the same member? > > Is that the only intended use? I believe that is the intention. I couldn't find relevant text in the Rationale. > In particular: is it a misuse of unions, to use them in order to > enable different memory-accesses (word, byte, etc.) to the same > portion of memory???? I have (mis)used it like this in above posts > quite often. > Is that strictly wrong? I think there might be an "out" for accessing any type as an array of unsigned char this way, but I believe that in general this is strictly wrong. I use "memcpy" to achieve a similar effect.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 18:10 -0700 |
| Message-ID | <kfnvck7xyst.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20359 |
Ben Pfaff <blp@cs.stanford.edu> writes: > John Reye <jononanon@googlemail.com> writes: > >> On May 3, 11:05 pm, Ben Pfaff <b...@cs.stanford.edu> wrote: >> So if you use a particular union access member... for a particular >> union in memory, then you should always access that particular union- >> variable, with the same member? >> >> Is that the only intended use? > > I believe that is the intention. I couldn't find relevant text > in the Rationale. If you read the Defect Report (sorry, I don't know the number offhand) that prompted the famous "type punning" footnote, I think you'll find that the type punning use cases were expected and intended all along, eg, even in C89/C90. I presume they were important to make defined because a significant amount of pre-ANSI C code relied on them working. >> In particular: is it a misuse of unions, to use them in order to >> enable different memory-accesses (word, byte, etc.) to the same >> portion of memory???? I have (mis)used it like this in above posts >> quite often. >> Is that strictly wrong? > > I think there might be an "out" for accessing any type as an > array of unsigned char this way, but I believe that in general > this is strictly wrong. [snip] How do you reconcile this view with the statement in clear and plain English about how union member access works to accomplish type punning? I think anyone who takes the time to read through the relevant sections defining the semantics involved will find accessing a union member is defined irrespective of which member was last set (although the result may depend on unspecified values and consequently undefined behavior because of trap representations, but the access itself is well-defined).
[toc] | [prev] | [next] | [standalone]
| From | nick_keighley_nospam@hotmail.com |
|---|---|
| Date | 2012-05-08 00:49 -0700 |
| Message-ID | <3688094.2254.1336463345478.JavaMail.geo-discussion-forums@vbki8> |
| In reply to | #20480 |
On Tuesday, May 8, 2012 2:10:42 AM UTC+1, Tim Rentsch wrote: > Ben Pfaff <blp@cs.stanford.edu> writes: > > > John Reye <jononanon@googlemail.com> writes: > > > >> On May 3, 11:05 pm, Ben Pfaff <b...@cs.stanford.edu> wrote: > >> So if you use a particular union access member... for a particular > >> union in memory, then you should always access that particular union- > >> variable, with the same member? > >> > >> Is that the only intended use? > > > > I believe that is the intention. I couldn't find relevant text > > in the Rationale. > > If you read the Defect Report (sorry, I don't know the > number offhand) that prompted the famous "type punning" > footnote, I think you'll find that the type punning use > cases were expected and intended all along, eg, even in > C89/C90. I presume they were important to make defined > because a significant amount of pre-ANSI C code relied > on them working. > > > >> In particular: is it a misuse of unions, to use them in order to > >> enable different memory-accesses (word, byte, etc.) to the same > >> portion of memory???? I have (mis)used it like this in above posts > >> quite often. > >> Is that strictly wrong? > > > > I think there might be an "out" for accessing any type as an > > array of unsigned char this way, but I believe that in general > > this is strictly wrong. [snip] > > How do you reconcile this view with the statement in > clear and plain English about how union member access > works to accomplish type punning? I think anyone who > takes the time to read through the relevant sections > defining the semantics involved will find accessing a > union member is defined irrespective of which member > was last set (although the result may depend on > unspecified values and consequently undefined behavior > because of trap representations, but the access itself > is well-defined). ******************************** Draft ANSI Standard 3.3.2.3 Structure and union members [...] Semantics [... 3rd para] With one exception, if a member of a union object is accessed after a value has been stored in a different member of the object, the behavior is implementation-defined./33/ One special guarantee is made in order to simplify the use of unions: If a union contains several structures that share a common initial sequence, and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them. Two structures share a common initial sequence if corresponding members have compatible types for a sequence of one or more initial members. ******************** I don't think "implementation defined" is the same as well defined. They could return zero every time if they wanted.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-05-08 06:37 -0400 |
| Message-ID | <joat0r$q3a$1@dont-email.me> |
| In reply to | #20495 |
On 05/08/2012 03:49 AM, nick_keighley_nospam@hotmail.com wrote: > On Tuesday, May 8, 2012 2:10:42 AM UTC+1, Tim Rentsch wrote: >> Ben Pfaff <blp@cs.stanford.edu> writes: ... >> If you read the Defect Report (sorry, I don't know the >> number offhand) that prompted the famous "type punning" >> footnote, I think you'll find that the type punning use >> cases were expected and intended all along, eg, even in >> C89/C90. I presume they were important to make defined >> because a significant amount of pre-ANSI C code relied >> on them working. ... >> How do you reconcile this view with the statement in >> clear and plain English about how union member access >> works to accomplish type punning? I think anyone who >> takes the time to read through the relevant sections >> defining the semantics involved will find accessing a >> union member is defined irrespective of which member >> was last set (although the result may depend on >> unspecified values and consequently undefined behavior >> because of trap representations, but the access itself >> is well-defined). > > ******************************** > Draft ANSI Standard > > 3.3.2.3 Structure and union members > [...] > Semantics > [... 3rd para] > With one exception, if a member of a union object is accessed after > a value has been stored in a different member of the object, the > behavior is implementation-defined./33/ One special guarantee is made > in order to simplify the use of unions: If a union contains several > structures that share a common initial sequence, and if the union > object currently contains one of these structures, it is permitted to > inspect the common initial part of any of them. Two structures share > a common initial sequence if corresponding members have compatible > types for a sequence of one or more initial members. > ******************** > > I don't think "implementation defined" is the same as well defined. They could return zero every time if they wanted. This is the "famous type-punning footnote" he referred to. It's footnote 95 in n1570.pdf: "If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’)." Footnotes are informative, not normative. Informative text is supposed to explain implications of what the normative text says, but if the normative text does not actually imply what the footnote says it does, the footnote is just plain wrong. The standard does not describe this reinterpretation or type punning anywhere in the normative text. Footnote 95 seems to be suggesting that this is a conclusion that can be reached from the combination of what it says in 6.5.2.3p3 about the semantics of the member selection operator, and what it says in 6.2.6 about the representations of types. It's not clear to me that this is actually the case. However, as a practical matter, footnote 95 documents what essentially all implementations of C have always done, and will continue to do, when translating such code. It unambiguously reflects the intent of the committee, whether or not that intent has actually been clearly expressed in the normative text of the standard. I think a programmer who relies upon footnote 95 as if it were, in fact, a correct summary of the normative text will never run into any trouble by reason of doing so. -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-08 07:49 -0700 |
| Message-ID | <kfn397awwvu.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20498 |
James Kuyper <jameskuyper@verizon.net> writes: [snip] > Footnote 95 seems to be suggesting that this is a conclusion that > can be reached from the combination of what it says in 6.5.2.3p3 > about the semantics of the member selection operator, and what it > says in 6.2.6 about the representations of types. It's not clear to > me that this is actually the case. For those who are interested, it isn't hard to verify that the normative text in C99/C11 supports what this footnote says in informative text. A previous posting of mine (posted, IIANM, in January of this year) listed the relevant sections or paragraphs that contribute to that. I guess JK didn't see that since apparently he routinely does not read my postings. > However, as a practical matter, footnote 95 documents what > essentially all implementations of C have always done, and will > continue to do, when translating such code. It unambiguously > reflects the intent of the committee, whether or not that intent > has actually been clearly expressed in the normative text of the > standard. I think a programmer who relies upon footnote 95 as if > it were, in fact, a correct summary of the normative text will > never run into any trouble by reason of doing so. Ditto.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-08 07:25 -0700 |
| Message-ID | <kfn7gwmwxzj.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20495 |
nick_keighley_nospam@hotmail.com writes: > On Tuesday, May 8, 2012 2:10:42 AM UTC+1, Tim Rentsch wrote: >> Ben Pfaff <blp@cs.stanford.edu> writes: >> >> > John Reye <jononanon@googlemail.com> writes: >> > >> >> On May 3, 11:05 pm, Ben Pfaff <b...@cs.stanford.edu> wrote: >> >> So if you use a particular union access member... for a particular >> >> union in memory, then you should always access that particular union- >> >> variable, with the same member? >> >> >> >> Is that the only intended use? >> > >> > I believe that is the intention. I couldn't find relevant text >> > in the Rationale. >> >> If you read the Defect Report (sorry, I don't know the >> number offhand) that prompted the famous "type punning" >> footnote, I think you'll find that the type punning use >> cases were expected and intended all along, eg, even in >> C89/C90. I presume they were important to make defined >> because a significant amount of pre-ANSI C code relied >> on them working. >> >> >> >> In particular: is it a misuse of unions, to use them in order to >> >> enable different memory-accesses (word, byte, etc.) to the same >> >> portion of memory???? I have (mis)used it like this in above posts >> >> quite often. >> >> Is that strictly wrong? >> > >> > I think there might be an "out" for accessing any type as an >> > array of unsigned char this way, but I believe that in general >> > this is strictly wrong. [snip] >> >> How do you reconcile this view with the statement in >> clear and plain English about how union member access >> works to accomplish type punning? I think anyone who >> takes the time to read through the relevant sections >> defining the semantics involved will find accessing a >> union member is defined irrespective of which member >> was last set (although the result may depend on >> unspecified values and consequently undefined behavior >> because of trap representations, but the access itself >> is well-defined). > > ******************************** > Draft ANSI Standard > > 3.3.2.3 Structure and union members > [...] > Semantics > [... 3rd para] > With one exception, if a member of a union object is accessed after > a value has been stored in a different member of the object, the > behavior is implementation-defined./33/ One special guarantee is made > in order to simplify the use of unions: If a union contains several > structures that share a common initial sequence, and if the union > object currently contains one of these structures, it is permitted to > inspect the common initial part of any of them. Two structures share > a common initial sequence if corresponding members have compatible > types for a sequence of one or more initial members. > ******************** This text corresponds to 6.3.2.3, fifth paragraph, in C90. The footnote /33/ referenced above is footnote 41 in the C90 document. That footnote says: The ``byte orders'' for scalar types are invisible to isolated programs that do not indulge in type punning (for example, by assigning to one member of a union and inspecting the storage by accessing another member that is an appropropriately sized array of character type), but must be accounted for when conforming to externally imposed storage layouts. > I don't think "implementation defined" is the same as well > defined. They could return zero every time if they wanted. I think the footnote makes it clear that the intention of the 'implementation-defined' wording is to reinterpret the underlying bytes in the new type. (Note that the quoted paragraph does not exclude character types from the 'implementation-defined' category.) This view is also supported by DR 283 (I was able to find it, fortunately easily, by "defect report" "type punning" as a google query) http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_283.htm which says in part (and written by someone on the committee) It is not perfectly clear that the C99 words have the same implications as the C89 words. So even though C89/C90 says 'implementation-defined' and C99 doesn't, the indications are that the meaning intended is the same in both cases, and also C11, which uses the same wording as C99. (There are minor changes in the C11 footnote relative to N1256, but these are incidental.) Summing up - I think you're right in some technical sense that the C90 allowed returning zero every time. But that isn't what was intended, nor AFAIAA what any implementor took it to mean. Unless there is a particular existing implementation that can be pointed to that exhibits the problem, the point seems moot; surely no current implementation would do anything other than follow the revised wording in C99 or C11.
[toc] | [prev] | [next] | [standalone]
| From | Ben Pfaff <blp@cs.stanford.edu> |
|---|---|
| Date | 2012-05-08 09:46 -0700 |
| Message-ID | <87pqae1uyz.fsf@blp.benpfaff.org> |
| In reply to | #20480 |
Tim Rentsch <txr@alumni.caltech.edu> writes: > Ben Pfaff <blp@cs.stanford.edu> writes: > >> John Reye <jononanon@googlemail.com> writes: >> >>> On May 3, 11:05 pm, Ben Pfaff <b...@cs.stanford.edu> wrote: >>> So if you use a particular union access member... for a particular >>> union in memory, then you should always access that particular union- >>> variable, with the same member? >>> >>> Is that the only intended use? >> >> I believe that is the intention. I couldn't find relevant text >> in the Rationale. > > If you read the Defect Report (sorry, I don't know the > number offhand) that prompted the famous "type punning" > footnote, I think you'll find that the type punning use > cases were expected and intended all along, eg, even in > C89/C90. I presume they were important to make defined > because a significant amount of pre-ANSI C code relied > on them working. Either I didn't know about that defect report or I'd forgotten it. Thanks for the correction.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-05-03 18:24 -0400 |
| Message-ID | <4FA3058E.8090601@verizon.net> |
| In reply to | #20352 |
On 05/03/2012 05:11 PM, John Reye wrote: ... > So if you use a particular union access member... for a particular > union in memory, then you should always access that particular union- > variable, with the same member? > > Is that the only intended use? Not quite. In C99, the standard was changed to describe how essentially all real-world implementations handled unions. Reading a different member than the last one written now sometimes has defined behavior, so long as it's not a trap representation. Specifically, it results in reinterpretation of the bits that were set by the write, in accordance with the representation for the member being read. Since the standard gives implementations a great deal of freedom with how values of different types are represented, code which takes advantage of that fact can never be portable. However, if you're willing to restrict the portability of your code to platforms where the relevant types are represented the way that your code assumes they are represented, it could be useful code - for those platforms. > In particular: is it a misuse of unions, to use them in order to > enable different memory-accesses (word, byte, etc.) to the same > portion of memory???? I have (mis)used it like this in above posts > quite often. > Is that strictly wrong? Whenever you read a member that is larger than the last one written to, the bytes that are not part of of the smaller member will have unspecified values. In that case, it's not sufficient to know how the different types are represented on this particular implementation of C. You'll also need to know precisely what that particular compiler does with such code. The portability of such code is correspondingly more restricted.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 18:24 -0700 |
| Message-ID | <kfnr4uvxy6j.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20361 |
James Kuyper <jameskuyper@verizon.net> writes: > On 05/03/2012 05:11 PM, John Reye wrote: > ... >> So if you use a particular union access member... for a particular >> union in memory, then you should always access that particular union- >> variable, with the same member? >> >> Is that the only intended use? > > Not quite. In C99, the standard was changed to describe how essentially > all real-world implementations handled unions. I believe this statement is a mispreresentation of the actual history; a more accurate statement is that the wording was changed but the intended behavior remained the same. There is evidence for this view in the Defect Report that prompted the footnote accompanying 6.5.2.3 p3 (which is currently #95 in N1570, but the footnote was also present in N1256, #82). > Reading a different > member than the last one written now sometimes has defined behavior, so > long as it's not a trap representation. Specifically, it results in > reinterpretation of the bits that were set by the write, in accordance > with the representation for the member being read. Since the standard > gives implementations a great deal of freedom with how values of > different types are represented, code which takes advantage of that fact > can never be portable. However, if you're willing to restrict the > portability of your code to platforms where the relevant types are > represented the way that your code assumes they are represented, it > could be useful code - for those platforms. And there are some signifcant cases where the representations are guaranteed to match, regardless of platform. >> In particular: is it a misuse of unions, to use them in order to >> enable different memory-accesses (word, byte, etc.) to the same >> portion of memory???? I have (mis)used it like this in above posts >> quite often. >> Is that strictly wrong? > > Whenever you read a member that is larger than the last one written to, > the bytes that are not part of of the smaller member will have > unspecified values. In that case, it's not sufficient to know how the > different types are represented on this particular implementation of C. > You'll also need to know precisely what that particular compiler does > with such code. The portability of such code is correspondingly more > restricted. That's right, and another important case might be mentioned. If the value written was a struct, then any padding bytes of the struct (and padding bits, presumably) take unspecified values. So unless what is being read matches up with (or is a subset of) one of the members of the struct type written, the same advisories about unspecified values and compiler dependency apply.
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2012-05-03 21:17 +0000 |
| Message-ID | <a0gav5Fg6kU1@mid.uni-berlin.de> |
| In reply to | #20344 |
John Reye <jononanon@googlemail.com> wrote:
> On May 3, 9:46 pm, Keith Thompson <ks...@mib.org> wrote:
> > As for whether it "works", that depends on what you want it to do. It
> > stores the value 0x12 in mystruct.u.c, which is also the first byte of
> > mystruct.u.b. If you access the first byte of mystruct.u.b,
> > *(char*)&mystruct.u.b, you'll get 0x12. If you access mystruct.u.b as
> > an int, you'll get garbage, possibly a trap representation.
> Will I really get garbage? I think not. The lowest-addressed byte is
> 0x12, and the other bytes of mystruct.u.b are what they were before,
> right?
As you have seen there are different architectures, having
different ways of representing e.g. an int - it can start
wtith the most significant bute at the lowest address or
with the least significant byte (or some other byte - the
C standard must be written in a way that it can be used
on all possible architectures). Thus when you change just
the byte at the lowest adress the value you get when you
read out the whole int can be different on different archi-
tectures.
What is meant when the C standard says that something is un-
defined is that it can't promise a certain outcome on all
possible architectures. Nothing more. Thus, if you want to
write a truely portable program you must avoid all kinds of
undefined behaviour. But if you write platform dependent
code and the platform defines what the C standard doesn't
it's completely fine to just use it, you just have to be
aware of that. Actually, without undefined behaviour you
wouldn't be able to write platform-dependent code, so it
would be impossible to e.g. write an operating system or
a device driver.
> A trap? How can that possibly be justified?
By the existence of machines with properties that may
seem unusual to you but for which probably good reasons
existed. The C standard can only mandate behaviour that
has a chance to be implemented on as many architectures
as possible - otherwise it would be impossible to write
a C compiler for them. So it's restricted to a smallest
common divder. And that's exactly one of the primary rea-
sons why C has been that successful and is still going
strong after 40 years - it's possible to have a C com-
piler for a supercomputer and for whatever system runs
a wrist-watch, a phone etc., and a program written in
standard C will run the same way on each of them.
> Why does the C language
> have unions then? What is the intended use of unions?
So that you can store values of different types in the
same location. But, of course, it hardly makes sense to
expect that after one has written a value of type A in-
to that location to be able to read something of a dif-
ferent type from it. Or do you often put a handkerchief
into a drawer and, when you open it again, it's a rabbit?
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 18:28 -0700 |
| Message-ID | <kfnmx5jxxye.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20354 |
jt@toerring.de (Jens Thoms Toerring) writes: > John Reye <jononanon@googlemail.com> wrote: > [snip] > >> Why does the C language >> have unions then? What is the intended use of unions? > > So that you can store values of different types in the > same location. But, of course, it hardly makes sense to > expect that after one has written a value of type A in- > to that location to be able to read something of a dif- > ferent type from it. Or do you often put a handkerchief > into a drawer and, when you open it again, it's a rabbit? Besides the useful cases that are platform dependent, there are also cases where the same representation is guaranteed between different types, on all platforms.
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web