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 | 17 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 3 of 3 — ← Prev page 1 2 [3]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-05-03 15:54 -0700 |
| Message-ID | <lnfwbgooxy.fsf@nuthaus.mib.org> |
| In reply to | #20344 |
John Reye <jononanon@googlemail.com> writes:
> 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?
No, the other bytes are not *necessarily* what they were before.
N1570 6.2.6.1p7 (I think it's already been quoted in this thread):
When a value is stored in a member of an object of union type,
the bytes of the object representation that do not correspond to
that member but do correspond to other members take unspecified
values.
If that other member's type has trap representations, then the
unspecified byte values could cause that member to take on a trap
representation.
If you really want to store 0x12 in the lowest-addressed byte of an int
without touching the other bytes, you can do it like this:
*(char*)&int_obj = 0x12;
But that's a somewhat odd thing to do. What goal are you trying to
achieve by storing 0x12 in the lowest-addressed byte of an int? If
you'll tell us that, perhaps we can help you find a better solution.
--
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 | Old Wolf <oldwolf@inspire.net.nz> |
|---|---|
| Date | 2012-05-06 22:32 -0700 |
| Message-ID | <ad3bf86e-136a-4c46-a6c5-77c0e8c5bbb2@ns1g2000pbc.googlegroups.com> |
| In reply to | #20344 |
On May 4, 8:35 am, John Reye <jonona...@googlemail.com> wrote: > A trap? How can that possibly be justified? Why does the C language > have unions then? What is the intended use of unions? Unions are for saving memory, when you know you need to store a value of some sort, but the value could be one of various types. If there were no unions you'd either have to have a struct (wasting memory), or use a byte buffer and write some ugly cast and alignment stuff. They're not supposed to be a hack to do type conversions, although that hasn't stopped people trying that over the years :)
[toc] | [prev] | [next] | [standalone]
| From | Jens Gustedt <jens.gustedt@loria.fr> |
|---|---|
| Date | 2012-05-07 08:26 +0200 |
| Message-ID | <4FA76B25.6030908@loria.fr> |
| In reply to | #20439 |
On 05/07/2012 07:32 AM, Old Wolf wrote: > On May 4, 8:35 am, John Reye <jonona...@googlemail.com> wrote: >> A trap? How can that possibly be justified? Why does the C language >> have unions then? What is the intended use of unions? > > Unions are for saving memory, when you know you > need to store a value of some sort, but the value > could be one of various types. If there were no > unions you'd either have to have a struct (wasting > memory), or use a byte buffer and write some ugly > cast and alignment stuff. > > They're not supposed to be a hack to do type conversions, > although that hasn't stopped people trying that over the years :) This is not hacking this is foreseen as such by the standard: - Unions have been the only way to guarantee that an object is correctly aligned for a collection of types. (Since C11 there are also _Alignas and friends.) - Other than casting pointers, unions avoid aliasing problems. Jens
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 18:31 -0700 |
| Message-ID | <kfnipg7xxuo.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20439 |
Old Wolf <oldwolf@inspire.net.nz> writes: > On May 4, 8:35 am, John Reye <jonona...@googlemail.com> wrote: >> A trap? How can that possibly be justified? Why does the C language >> have unions then? What is the intended use of unions? > > Unions are for saving memory, when you know you > need to store a value of some sort, but the value > could be one of various types. If there were no > unions you'd either have to have a struct (wasting > memory), or use a byte buffer and write some ugly > cast and alignment stuff. > > They're not supposed to be a hack to do type conversions, > [snip] In fact they were, and are. And that's why the Standard defines how such cases work.
[toc] | [prev] | [next] | [standalone]
| From | Jens Gustedt <jens.gustedt@loria.fr> |
|---|---|
| Date | 2012-05-03 23:18 +0200 |
| Message-ID | <4FA2F620.5080305@loria.fr> |
| In reply to | #20338 |
Am 05/03/2012 09:46 PM, schrieb Keith Thompson:
> 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.
C11 has anonymous structures and unions (6.7.2.1 p 13)
Jens
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-05-03 15:58 -0700 |
| Message-ID | <lnbom4oosd.fsf@nuthaus.mib.org> |
| In reply to | #20355 |
Jens Gustedt <jens.gustedt@loria.fr> writes:
> Am 05/03/2012 09:46 PM, schrieb Keith Thompson:
>> 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.
>
> C11 has anonymous structures and unions (6.7.2.1 p 13)
Interesting.
Here's the paragraph (quoting N1570):
An unnamed member whose type specifier is a structure specifier
with no tag is called an *anonymous structure*; an unnamed member
whose type specifier is a union specifier with no tag is called
an *anonymous union*. The members of an anonymous structure or
union are considered to be members of the containing structure
or union. This applies recursively if the containing structure
or union is also anonymous.
--
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 | pete <pfiland@mindspring.com> |
|---|---|
| Date | 2012-05-04 00:25 -0400 |
| Message-ID | <4FA35A2E.6B0B@mindspring.com> |
| In reply to | #20303 |
John Reye wrote:
>
> 1)
> a[i] = i++;
>
> http://c-faq.com/expr/evalorder1.html
>
> So this attempt at optimisation is wrong:
>
> int i;
> int a[10];
> for (i = 0; i < sizeof(a); )
> a[i] = i++; /* set a to {1, 2, 3, ...} */
>
> Correctly optimized, it should be:
> for (i = 0; i < sizeof(a); )
> i = a[i] = i+1; /* set a to {1, 2, 3, ...} */
No. That's wrong.
Concerning
i = a[i] = i+1;
Assignment, is not a sequence point.
The above code does not say whether the value of (i+1)
is stored first in (a[i]) or in (i).
This is defined:
for (i = 0; i < sizeof a / sizeof *a; ++i) {
a[i] = i + 1; /* set a to {1, 2, 3, ...} */
}
--
pete
[toc] | [prev] | [next] | [standalone]
| From | John Reye <jononanon@googlemail.com> |
|---|---|
| Date | 2012-05-03 22:28 -0700 |
| Message-ID | <6d809568-c4a1-4223-ada2-5e031db0e896@l15g2000vbv.googlegroups.com> |
| In reply to | #20371 |
On May 4, 6:25 am, pete <pfil...@mindspring.com> wrote:
> No. That's wrong.
> Concerning
> i = a[i] = i+1;
> Assignment, is not a sequence point.
> The above code does not say whether the value of (i+1)
> is stored first in (a[i]) or in (i).
>
> This is defined:
>
> for (i = 0; i < sizeof a / sizeof *a; ++i) {
> a[i] = i + 1; /* set a to {1, 2, 3, ...} */
> }
>
> --
> pete
I believe that is incorrect.
The sequence point only makes a difference for statements that contain
side-effects.
So this is not allowed
a[i] = i++;
because = is no sequence point, and contains side-effects (i++).
See http://c-faq.com/expr/seqpoints.html
But this is very much allowed:
i = a[i] = i+1;
It uses the normal fact assignment is right-associative and that no
side-effects exist.
Also (less importantly): it may be more efficient than doing
a[i] = i+1;
i++;
since I am helping an exessively "simple" compiler understand, that it
need not load i into a register for the 2nd line (to then be
incremented). Instead, the incremented value (i+1) may already be in a
register, and (after the loop... if i is still needed) ready to be
written to the memory-location of i.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-05-04 07:33 -0400 |
| Message-ID | <jo0eqg$97q$1@dont-email.me> |
| In reply to | #20372 |
On 05/04/2012 01:28 AM, John Reye wrote:
> On May 4, 6:25�am, pete <pfil...@mindspring.com> wrote:
>> No. That's wrong.
>> Concerning
>> � � i = a[i] = i+1;
>> Assignment, is not a sequence point.
>> The above code does not say whether the value of (i+1)
>> is stored first in (a[i]) or in (i).
>>
>> This is defined:
>>
>> � � for (i = 0; i < sizeof a / sizeof *a; ++i) {
>> � � � � a[i] = i + 1; � � � � � � � � � /* set a to {1, 2, 3, ...} */
>> � � }
>>
>> --
>> pete
>
> I believe that is incorrect.
> The sequence point only makes a difference for statements that contain
> side-effects.
> So this is not allowed
> a[i] = i++;
> because = is no sequence point, and contains side-effects (i++).
> See http://c-faq.com/expr/seqpoints.html
>
>
>
>
> But this is very much allowed:
> i = a[i] = i+1;
> It uses the normal fact assignment is right-associative and that no
> side-effects exist.
That statement reflects a common misunderstanding of what "side-effect"
means. You might think that the fact that i=3 sets the value of i to 3
is the main effect; the fact that i=3 is itself an expression with a
value of 3 is less important (it's certainly not a fact that I use very
often). However, what the standard sees things the other way around. It
says:
> Accessing a volatile object, modifying an object, modifying a file, or calling a function
> that does any of those operations are all _side effects_, (5.1.2.3p2)
I've used underscores to mark the fact that "side effect" is in italics,
which is the standard's convention for marking this sentence as the
definition of the italicized term. The expression "i = a[i] = i + 1"
modifies two objects: 'i' and a[i], so it does indeed have side effects.
In C99, the expression "i = a[i] = i + 1" had undefined behavior because
the value of i was both stored by this expression, and read for purposes
other than determining the value to be stored in 'i', without any
intervening sequence points to determine which of those events occurs
first. The exception for determining the value to be stored allows "i =
i + 1", since the value of 'i' must be read in order to calculate the
value of 'i+1' which is to be stored in i.
However, in the case of 'i = a[i] = i+1", the value of 'i' is also read
to determine which element of 'a' gets updated. It's unclear whether the
value of i should be updated before or after determining which element
to update. The C committee could have chosen to specify the sequence,
but they reached the conclusion that such code is inherently confusing,
and therefore should be discouraged. They did this by not merely leaving
the sequence unspecified, but explicitly stating that the behavior of
your entire program is undefined if it uses such code. The standard
never says that you can't do something; it only tells you what you can
and cannot depend upon happening, if you should choose to do something.
In this case, the standard imposes NO requirements on the behavior of a
program containing such code; you can't even count on it being allowed
to compile.
This is not a hard requirement to work around. Just make the desired
sequence crystal clear by writing either:
a[i] = i + 1;
i = a[i];
or
i = i + 1;
a[i] = i;
whichever one matches what you actually intended i=a[i]= i+1 to do.
The relevant clause in C99 was one of the most confusingly worded parts
of that standard, and provoked a lot of argument. In C2011, I gather
that this whole issue has been more precisely defined by rewording
things in terms of the "visible sequence of side effect" and by
specifying that the evaluation of each expression may be "sequenced
before", "sequenced after", or "indeterminately sequenced" relative to
the evaluation of other expressions. The C2011 wording is greatly
complicated by the fact that it must now deal with the possibility of
multi-threaded code. As a result, I've not had time to review exactly
what the new standard says about such things. The new wording might make
the behavior of this code well-defined; but I doubt it - I think the
committee still believes that such code is inherently confusing, and
therefore should still be discouraged.
--
James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 19:20 -0700 |
| Message-ID | <kfn62c7xvjt.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20383 |
James Kuyper <jameskuyper@verizon.net> writes:
> On 05/04/2012 01:28 AM, John Reye wrote:
>> On May 4, 6:25 am, pete <pfil...@mindspring.com> wrote:
>>> No. That's wrong.
>>> Concerning
>>> i = a[i] = i+1;
>>> Assignment, is not a sequence point.
>>> The above code does not say whether the value of (i+1)
>>> is stored first in (a[i]) or in (i).
>>>
>>> This is defined:
>>>
>>> for (i = 0; i < sizeof a / sizeof *a; ++i) {
>>> a[i] = i + 1; /* set a to {1, 2, 3, ...} */
>>> }
>>>
>>> --
>>> pete
>>
>> I believe that is incorrect.
>> The sequence point only makes a difference for statements that contain
>> side-effects.
>> So this is not allowed
>> a[i] = i++;
>> because = is no sequence point, and contains side-effects (i++).
>> See http://c-faq.com/expr/seqpoints.html
>>
>>
>>
>>
>> But this is very much allowed:
>> i = a[i] = i+1;
>> It uses the normal fact assignment is right-associative and that no
>> side-effects exist.
>
> [snip description of side-effects]
>
> In C99, the expression "i = a[i] = i + 1" had undefined behavior because
> the value of i was both stored by this expression, and read for purposes
> other than determining the value to be stored in 'i', without any
> intervening sequence points to determine which of those events occurs
> first. The exception for determining the value to be stored allows "i =
> i + 1", since the value of 'i' must be read in order to calculate the
> value of 'i+1' which is to be stored in i.
>
> However, in the case of 'i = a[i] = i+1", the value of 'i' is also read
> to determine which element of 'a' gets updated. It's unclear whether the
> value of i should be updated before or after determining which element
> to update. The C committee could have chosen to specify the sequence,
> but they reached the conclusion that such code is inherently confusing,
> and therefore should be discouraged. [snip elaboration]
There is evidence to the contrary, namely that they intended all
along that such uses be well-defined, and it was only due to a
poor choice of wording (in earlier Standards) that it wasn't.
It is unambiguously well-defined under C11.
> The relevant clause in C99 was one of the most confusingly
> worded parts of that standard, and provoked a lot of argument.
I would say it was poorly worded rather than confusingly
worded; IMO the meaning was clear, it was just a poor
choice of phrasing that caused confusion. In any case,
C11 has fixed that.
> In C2011, I gather
> that this whole issue has been more precisely defined by rewording
> things in terms of the "visible sequence of side effect" and by
> specifying that the evaluation of each expression may be "sequenced
> before", "sequenced after", or "indeterminately sequenced" relative to
> the evaluation of other expressions. The C2011 wording is greatly
> complicated by the fact that it must now deal with the possibility of
> multi-threaded code. As a result, I've not had time to review exactly
> what the new standard says about such things. The new wording might make
> the behavior of this code well-defined; but I doubt it - I think the
> committee still believes that such code is inherently confusing, and
> therefore should still be discouraged.
So although he hasn't read what it says exactly, he feels
free to conjecture what it does say? That's amusing.
Having taken some amount of time to study the documents available
on how to specify order of evaluation, including C11, I would
say this --
First, the behavior in question is well-defined under C11.
Second, several formal models for how "order of evaluation"
should be specified in C were discussed over the years by the
committee, and AFAIK all of them defined the semantics of
multiple assignments like this one; certainly the ones I
remember reading did, and the current one (in C11) does. So all
the evidence I've seen supports the idea that the committee
thought it important to define such cases, and I'm not aware of
any evidence that supports the view that the committee believes
such code is confusing or should be discouraged.
But in any case, under C11 the behavior is well-defined.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 18:50 -0700 |
| Message-ID | <kfnaa1jxwyc.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20372 |
John Reye <jononanon@googlemail.com> writes:
> On May 4, 6:25 am, pete <pfil...@mindspring.com> wrote:
>> No. That's wrong.
>> Concerning
>> i = a[i] = i+1;
>> Assignment, is not a sequence point.
>> The above code does not say whether the value of (i+1)
>> is stored first in (a[i]) or in (i).
>>
>> This is defined:
>>
>> for (i = 0; i < sizeof a / sizeof *a; ++i) {
>> a[i] = i + 1; /* set a to {1, 2, 3, ...} */
>> }
>>
>> --
>> pete
>
> I believe that is incorrect.
> The sequence point only makes a difference for statements that contain
> side-effects.
> So this is not allowed
> a[i] = i++;
> because = is no sequence point, and contains side-effects (i++).
> See http://c-faq.com/expr/seqpoints.html
The latest C standard uses more precise terminology regarding
sequencing. If you haven't gotten that, or this close approximation
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
, I encourage you to do so.
> But this is very much allowed:
> i = a[i] = i+1;
> It uses the normal fact assignment is right-associative and that no
> side-effects exist. [snip]
You're right that it is allowed. However there are two side-effects
(ie, the assignments), and being right-associative plays into
the question only partially. What is more important is that
the side-effect of storing into 'i' is /sequenced after/ the
value computations of the two operands (which in this case
are 'i' and 'a[i] = i+1'). It is because of that sequencing
relationship that the store into 'i' must follow the computation
of which element a is to be accessed with the expression 'a[i]'.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 18:42 -0700 |
| Message-ID | <kfnehqvxxcg.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20371 |
pete <pfiland@mindspring.com> writes:
> John Reye wrote:
>>
>> 1)
>> a[i] = i++;
>>
>> http://c-faq.com/expr/evalorder1.html
>>
>> So this attempt at optimisation is wrong:
>>
>> int i;
>> int a[10];
>> for (i = 0; i < sizeof(a); )
>> a[i] = i++; /* set a to {1, 2, 3, ...} */
>>
>> Correctly optimized, it should be:
>> for (i = 0; i < sizeof(a); )
>> i = a[i] = i+1; /* set a to {1, 2, 3, ...} */
>
> No. That's wrong.
> Concerning
> i = a[i] = i+1;
> Assignment, is not a sequence point.
> The above code does not say whether the value of (i+1)
> is stored first in (a[i]) or in (i). [snip alternative]
The behavior of
i = a[i] = i+1;
is well-defined. I refer you to 6.5.16 p3 in N1570, specifically
the second-to-last sentence. By the time the store into 'i'
commences, the value (lvalue) computation of 'a[i]' has already
completed, because it is sequenced before delivering the value
to be stored into 'i'.
The stores to 'i' and 'a[i]' may happen in any order, but the
lvalue 'a[i]' must be determined before any store into 'i'.
[toc] | [prev] | [next] | [standalone]
| From | pete <pfiland@mindspring.com> |
|---|---|
| Date | 2012-05-07 23:45 -0400 |
| Message-ID | <4FA896E6.B8E@mindspring.com> |
| In reply to | #20484 |
Tim Rentsch wrote:
>
> pete <pfiland@mindspring.com> writes:
>
> > John Reye wrote:
> >>
> >> 1)
> >> a[i] = i++;
> >>
> >> http://c-faq.com/expr/evalorder1.html
> >>
> >> So this attempt at optimisation is wrong:
> >>
> >> int i;
> >> int a[10];
> >> for (i = 0; i < sizeof(a); )
> >> a[i] = i++; /* set a to {1, 2, 3, ...} */
> >>
> >> Correctly optimized, it should be:
> >> for (i = 0; i < sizeof(a); )
> >> i = a[i] = i+1; /* set a to {1, 2, 3, ...} */
> >
> > No. That's wrong.
> > Concerning
> > i = a[i] = i+1;
> > Assignment, is not a sequence point.
> > The above code does not say whether the value of (i+1)
> > is stored first in (a[i]) or in (i). [snip alternative]
>
> The behavior of
>
> i = a[i] = i+1;
>
> is well-defined. I refer you to 6.5.16 p3 in N1570, specifically
> the second-to-last sentence. By the time the store into 'i'
> commences, the value (lvalue) computation of 'a[i]' has already
> completed, because it is sequenced before delivering the value
> to be stored into 'i'.
>
> The stores to 'i' and 'a[i]' may happen in any order, but the
> lvalue 'a[i]' must be determined before any store into 'i'.
I don't see where it says what you say that it says.
Concerning (a[i] = i+1),
"the value of the left operand after the assignment"
can be determined before the assignment
and without knowing which array element a[i] refers to.
You don't have to know which array element a[i] refers to,
to know
what the value of (i+1) converted to whichever type (a[i]) has,
is.
n1570
6.5.16 Assignment operators
Semantics
3 An assignment operator stores a value
in the object designated by the left operand.
An assignment expression has
the value of the left operand after the assignment,111)
but is not an lvalue.
The type of an assignment expression
is the type the left operand would have after lvalue conversion.
The side effect of updating the stored value of the left operand
is sequenced after the value computations of the left
and right operands.
The evaluations of the operands are unsequenced.
--
pete
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-07 23:01 -0700 |
| Message-ID | <kfnsjfbw6rt.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20488 |
pete <pfiland@mindspring.com> writes:
> Tim Rentsch wrote:
>>
>> pete <pfiland@mindspring.com> writes:
>>
>> > John Reye wrote:
>> >>
>> >> 1)
>> >> a[i] = i++;
>> >>
>> >> http://c-faq.com/expr/evalorder1.html
>> >>
>> >> So this attempt at optimisation is wrong:
>> >>
>> >> int i;
>> >> int a[10];
>> >> for (i = 0; i < sizeof(a); )
>> >> a[i] = i++; /* set a to {1, 2, 3, ...} */
>> >>
>> >> Correctly optimized, it should be:
>> >> for (i = 0; i < sizeof(a); )
>> >> i = a[i] = i+1; /* set a to {1, 2, 3, ...} */
>> >
>> > No. That's wrong.
>> > Concerning
>> > i = a[i] = i+1;
>> > Assignment, is not a sequence point.
>> > The above code does not say whether the value of (i+1)
>> > is stored first in (a[i]) or in (i). [snip alternative]
>>
>> The behavior of
>>
>> i = a[i] = i+1;
>>
>> is well-defined. I refer you to 6.5.16 p3 in N1570, specifically
>> the second-to-last sentence. By the time the store into 'i'
>> commences, the value (lvalue) computation of 'a[i]' has already
>> completed, because it is sequenced before delivering the value
>> to be stored into 'i'.
>>
>> The stores to 'i' and 'a[i]' may happen in any order, but the
>> lvalue 'a[i]' must be determined before any store into 'i'.
>
> I don't see where it says what you say that it says.
>
> Concerning (a[i] = i+1),
> "the value of the left operand after the assignment"
> can be determined before the assignment
> and without knowing which array element a[i] refers to.
>
> You don't have to know which array element a[i] refers to,
> to know
> what the value of (i+1) converted to whichever type (a[i]) has,
> is.
>
> n1570
> 6.5.16 Assignment operators
> Semantics
> 3 An assignment operator stores a value
> in the object designated by the left operand.
> An assignment expression has
> the value of the left operand after the assignment,111)
> but is not an lvalue.
> The type of an assignment expression
> is the type the left operand would have after lvalue conversion.
> The side effect of updating the stored value of the left operand
> is sequenced after the value computations of the left
> and right operands.
> The evaluations of the operands are unsequenced.
The missing piece (which I should have mentioned before -
sorry about that) is 6.5 p1, last sentence:
The value computations of the operands of an operator are
sequenced before the value computation of the result of
the operator.
So the lvalue 'a[i]' must be computed before there is a value
(produced by the intermediate '=' operator) to store into 'i'.
[toc] | [prev] | [next] | [standalone]
| From | pete <pfiland@mindspring.com> |
|---|---|
| Date | 2012-05-08 06:28 -0400 |
| Message-ID | <4FA8F568.4D99@mindspring.com> |
| In reply to | #20490 |
Tim Rentsch wrote:
>
> pete <pfiland@mindspring.com> writes:
>
> > Tim Rentsch wrote:
> >>
> >> pete <pfiland@mindspring.com> writes:
> >>
> >> > John Reye wrote:
> >> >>
> >> >> 1)
> >> >> a[i] = i++;
> >> >>
> >> >> http://c-faq.com/expr/evalorder1.html
> >> >>
> >> >> So this attempt at optimisation is wrong:
> >> >>
> >> >> int i;
> >> >> int a[10];
> >> >> for (i = 0; i < sizeof(a); )
> >> >> a[i] = i++; /* set a to {1, 2, 3, ...} */
> >> >>
> >> >> Correctly optimized, it should be:
> >> >> for (i = 0; i < sizeof(a); )
> >> >> i = a[i] = i+1; /* set a to {1, 2, 3, ...} */
> >> >
> >> > No. That's wrong.
> >> > Concerning
> >> > i = a[i] = i+1;
> >> > Assignment, is not a sequence point.
> >> > The above code does not say whether the value of (i+1)
> >> > is stored first in (a[i]) or in (i). [snip alternative]
> >>
> >> The behavior of
> >>
> >> i = a[i] = i+1;
> >>
> >> is well-defined. I refer you to 6.5.16 p3 in N1570, specifically
> >> the second-to-last sentence. By the time the store into 'i'
> >> commences, the value (lvalue) computation of 'a[i]' has already
> >> completed, because it is sequenced before delivering the value
> >> to be stored into 'i'.
> >>
> >> The stores to 'i' and 'a[i]' may happen in any order, but the
> >> lvalue 'a[i]' must be determined before any store into 'i'.
> >
> > I don't see where it says what you say that it says.
> >
> > Concerning (a[i] = i+1),
> > "the value of the left operand after the assignment"
> > can be determined before the assignment
> > and without knowing which array element a[i] refers to.
> >
> > You don't have to know which array element a[i] refers to,
> > to know
> > what the value of (i+1) converted to whichever type (a[i]) has,
> > is.
> >
> > n1570
> > 6.5.16 Assignment operators
> > Semantics
> > 3 An assignment operator stores a value
> > in the object designated by the left operand.
> > An assignment expression has
> > the value of the left operand after the assignment,111)
> > but is not an lvalue.
> > The type of an assignment expression
> > is the type the left operand would have after lvalue conversion.
> > The side effect of updating the stored value of the left operand
> > is sequenced after the value computations of the left
> > and right operands.
> > The evaluations of the operands are unsequenced.
>
> The missing piece (which I should have mentioned before -
> sorry about that) is 6.5 p1, last sentence:
>
> The value computations of the operands of an operator are
> sequenced before the value computation of the result of
> the operator.
>
> So the lvalue 'a[i]' must be computed before there is a value
> (produced by the intermediate '=' operator) to store into 'i'.
I think that you may be right.
I also made an obsolete statement elsewhere in this thread
about the postfix increment operator.
--
pete
[toc] | [prev] | [next] | [standalone]
| From | pete <pfiland@mindspring.com> |
|---|---|
| Date | 2012-05-08 06:37 -0400 |
| Message-ID | <4FA8F767.689F@mindspring.com> |
| In reply to | #20496 |
pete wrote: > > Tim Rentsch wrote: > > The value computations of the operands of an operator are > > sequenced before the value computation of the result of > > the operator. > > > > So the lvalue 'a[i]' must be computed before there is a value > > (produced by the intermediate '=' operator) to store into 'i'. > > I think that you may be right. > I also made an obsolete statement elsewhere in this thread > about the postfix increment operator. Actually, it was in the "pointer arithmetic question" thread. -- pete
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-08 06:19 -0700 |
| Message-ID | <kfnfwbax12o.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20499 |
pete <pfiland@mindspring.com> writes: > pete wrote: >> >> Tim Rentsch wrote: > >> > The value computations of the operands of an operator are >> > sequenced before the value computation of the result of >> > the operator. >> > >> > So the lvalue 'a[i]' must be computed before there is a value >> > (produced by the intermediate '=' operator) to store into 'i'. >> >> I think that you may be right. >> I also made an obsolete statement elsewhere in this thread >> about the postfix increment operator. > > Actually, it was in the "pointer arithmetic question" thread. Aha, I see that... will respond there.
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.c
csiph-web