Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > sequence points in subexpressions

Reply
Thread Tools

sequence points in subexpressions

 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      12-14-2009
Beej Jorgensen wrote:

> On 12/14/2009 02:07 PM, Johannes Schaub (litb) wrote:
>> But i still think it is UB in C99. The additional requirements about
>> value computations are missing from C99 and so the "Between the previous
>> and next sequence point an object shall have its stored value modified at
>> most once by the evaluation of an expression." seems to render behavior
>> UB.

>
> I'm still not sure because I'm not sure where the "next sequence point"
> is in C99.
>
> A B C D
> | | | |
> i = (i, i++, i) + 1
>
> i is modified twice between A and D, which causes UB by your above cite.
> But what of sequence point C? Does it not count?
>

I think "previous and next" means the sequence point prior to the point of
execution in the execution sequence, and next to the point of execution. In
the UB scenario, the assignment happens between B and C. If it happens
between C and D, behavior is not UB. Where it happens is unspecified.

I share your worry as i don't know what is meant in 6.5.16/3 by "The side
effect of updating the stored value of the left operand shall
occur between the previous and the next sequence point.". In general, i
think sequence points are not at certain places in code, but in the
execution of it (in describing the comma operator, for instance, C99 says
"The left operand of a comma operator is evaluated as a void expression;
there is a sequence point after its evaluation." - it doesn't say "there is
a sequence point after the first operand.". But then in the description of
the assignment expression, it appears to refer to the "enclosing" full
expression sequence points - weird!

> I can't help but feel that C99 is missing a needed dimension in the
> model, and 201x is addressing this. (Though it might have been a
> necessary addition due to the threading stuff [5.1.2.4 "Multi-threaded
> executions and data races"] which heavily relies on sequencing side
> effects.)
>


Same here
 
Reply With Quote
 
 
 
 
Peter Nilsson
Guest
Posts: n/a
 
      12-14-2009
pete <(E-Mail Removed)> wrote:
> Beej Jorgensen wrote:
> > pete wrote:
> > > Beej Jorgensen wrote:
> > > > o *For the value computation of (i,i++,i) to be
> > > > complete, i++'s side*effects must be complete.
> > >
> > > I disagree.
> > > I know that the value of (i,i++,i) is one greater
> > > than the original value of (i).
> > > I computed that without accomplishing any side
> > > effects.

> >
> > ... you're arguing the side effects don't necessarily
> > take place at the sequence point, is that right?

>
> No.
> I'm saying that the word "evaluation" includes side
> effects, and I'm saying that value of an expression can
> be determined and used prior to the evaluation of that
> expression being completed.


Consider...

int f(int i) { printf("%d\n", i); return i }
int i = 42;
i = f(i) + 1;

An implementation could deduce that i ends up with the value
of one more than it started with. So then, could it do the
assignment _before_ the function call?

One would hope not. Why should the situation be any different
for...

i = (printf("%d\n", i), i) + 1;

....or...

i = (printf("%d\n", i++), i);

....or...

int f(int *i) { printf("%d\n", *i); return ++*i; }
i = f(&i);

Yes, an implementation can make deductions about the
expression, but the middle sequence point(s), and the
concept that the rhs must be evaluated, guarantees there
are no multiple assignments of the same object, and no
access for a purpose other than to compute the new
value, between sequence points for the cases above.

I don't know if C90 and C99 make this clear, but
without it, C would be defective IMO.

--
Peter
 
Reply With Quote
 
 
 
 
Beej Jorgensen
Guest
Posts: n/a
 
      12-14-2009
On 12/14/2009 02:36 PM, Johannes Schaub (litb) wrote:
> Beej Jorgensen wrote:
>>
>> A B C D
>> | | | |
>> i = (i, i++, i) + 1
>>
>> i is modified twice between A and D, which causes UB by your above cite.
>> But what of sequence point C? Does it not count?
>>

> I think "previous and next" means the sequence point prior to the point of
> execution in the execution sequence, and next to the point of execution. In
> the UB scenario, the assignment happens between B and C.


Hmmm. Is that possible? I think it being possible hinges on us being
able to use the value of (i,i++,i) before the i++ side effect takes
place (since that value is needed for the assignment into i.)

C99 5.1.2.3p2:
# At certain specified points in the execution sequence called sequence
# points, all side effects of previous evaluations shall be complete and
# no side effects of subsequent evaluations shall have taken place.

So the assignment would have to count as a "previous evaluation" by
sequence point C...? That would imply that the entire + calculation
would also need to be complete by sequence point C...

C99 5.1.2.3p2 is all about "side effects"... it doesn't say anything
about the value computations. (in 201x the same paragraph clarifies
that it applies to both "every value computation and side effect".) Are
the value computations in C99 free to run off into the glorious future
and do all kinds of stuff beyond the sequence point before the sequence
point is hit? So, then, is this conforming pseudo-assembly that
demonstrates the UB in C99:

i = (i, i++, i) + 1

0 ;; == sequence point A ==
1 ;; == sequence point B ==
2 inc_i = i + 1
3 i = inc_i + 1 ; assignment
4 i = inc_i ; postincrement
5 ;; == sequence point C ==
6 ;; == sequence point D ==

Note that lines 3 and 4 can be interchanged, leading to the undefined
behavior.

(In 201x, I think this pseudo-assembly would be non-conforming because
the line 3 assignment would have to occur after sequence point C--thus
leading to a well-defined result.)

-Beej

 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-15-2009
On 2009-12-14, Beej Jorgensen <(E-Mail Removed)> wrote:
> On 12/14/2009 02:36 PM, Johannes Schaub (litb) wrote:
>> Beej Jorgensen wrote:
>>>
>>> A B C D
>>> | | | |
>>> i = (i, i++, i) + 1
>>>
>>> i is modified twice between A and D, which causes UB by your above cite.
>>> But what of sequence point C? Does it not count?
>>>

>> I think "previous and next" means the sequence point prior to the point of
>> execution in the execution sequence, and next to the point of execution. In
>> the UB scenario, the assignment happens between B and C.

>
> Hmmm. Is that possible?


Not even by any halfway reasonable interpretation of C90.
 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      12-15-2009
Kenneth Brody wrote:

<snip>

> Now, had the original example used "i" instead of "1" outside the parens:
>
> i = (i, i++, i) + i;
>
> then this would be a totally different question. I'm not certain if
> this constitutes "undefined" or "unspecified". However, given the same
> sequence points because of the comma operators, I would have to lean
> towards "unspecified".


I would say it is undefined, because there is no sequence point between
the i++ and the +i. It would still be undefined for the same reason if
you had
j = (i, i++, i) + i;
--
Flash Gordon
 
Reply With Quote
 
Beej Jorgensen
Guest
Posts: n/a
 
      12-15-2009
On 12/14/2009 04:15 PM, Kaz Kylheku wrote:
> On 2009-12-14, Beej Jorgensen <(E-Mail Removed)> wrote:
>> Hmmm. Is that possible?

>
> Not even by any halfway reasonable interpretation of C90.


I grant that, but what about my 25% reasonable interpretation?

-Beej


 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      12-15-2009
Richard wrote:

> Kenneth Brody <(E-Mail Removed)> writes:
>
>> Richard wrote:
>>> Flash Gordon <(E-Mail Removed)> writes:
>>>
>>>> Kenneth Brody wrote:
>>>>
>>>> <snip>
>>>>
>>>>> Now, had the original example used "i" instead of "1" outside the
>>>>> parens:
>>>>>
>>>>> i = (i, i++, i) + i;
>>>>>
>>>>> then this would be a totally different question. I'm not certain if
>>>>> this constitutes "undefined" or "unspecified". However, given the
>>>>> same sequence points because of the comma operators, I would have to
>>>>> lean towards "unspecified".
>>>> I would say it is undefined, because there is no sequence point between
>>>> the i++ and the +i. It would still be undefined for the same reason if
>>>> you had
>>>> j = (i, i++, i) + i;
>>>
>>> The simple fact is that the sequence is i, i++ and then i. It must be
>>> done in that order. It would be ludicrous if the resultant was not the
>>> initial value of i+1 IMO since the whole point of "sequence points"
>>> would be lost.

>>
>> But, the "+i" outside of the parens makes this, I believe,
>> "unspecified".

>
> Why? The left hand expression in brackets is a sequence of
> expressions. The i++ MUST be evaluated before the last one or it makes
> a mockery of the entire reason for sequence points IMO.
>


You are missing that "i" is an "ihh" not a "one". So the previous value in
"i" is accessed *not* only to determine the new value to be stored, but
independently of the store action. This is what makes it undefined behavior.
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      12-15-2009
Kenneth Brody wrote:

> Flash Gordon wrote:
>> Kenneth Brody wrote:
>>
>> <snip>
>>
>>> Now, had the original example used "i" instead of "1" outside the
>>> parens:
>>>
>>> i = (i, i++, i) + i;
>>>
>>> then this would be a totally different question. I'm not certain if
>>> this constitutes "undefined" or "unspecified". However, given the
>>> same sequence points because of the comma operators, I would have to
>>> lean towards "unspecified".

>>
>> I would say it is undefined, because there is no sequence point between
>> the i++ and the +i. It would still be undefined for the same reason if
>> you had
>> j = (i, i++, i) + i;

>
> You don't see any sequence point between "i++" and "+i" here?
>
> i = (i, i++, i) + i;
> ^ ^
> here and here
>


Those are not sequence points between "i++" and "+i". Those are sequence
points between "i", "i++" and "i". Notice that when we talk about "sequence
point between A and B" we are not talking about tokens, but about
evaluations - in the above case, evaluations of i++ and +i.
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-15-2009
On 2009-12-15, Richard <(E-Mail Removed)> wrote:
> Kenneth Brody <(E-Mail Removed)> writes:
>>>> j = (i, i++, i) + i;
>>>
>>> The simple fact is that the sequence is i, i++ and then i. It must be done
>>> in that order. It would be ludicrous if the resultant was not the
>>> initial value of i+1 IMO since the whole point of "sequence points"
>>> would be lost.

>>
>> But, the "+i" outside of the parens makes this, I believe,
>> "unspecified".

>
> Why? The left hand expression in brackets is a sequence of
> expressions. The i++ MUST be evaluated before the last one or it makes
> a mockery of the entire reason for sequence points IMO.


The + i makes it undefined. The operands of + can be evaluated in any
orer, nicluding interleaved and parallel. So this use violates the
second rule. The left operand of + makes modifications to i, which
race against the access of i on the opposite side. We don't know whether
this right hand side i is accessed before, during or after the i++
expression embedded in the left side.
 
Reply With Quote
 
Beej Jorgensen
Guest
Posts: n/a
 
      12-15-2009
On 12/15/2009 10:42 AM, Richard wrote:
>>>> Kenneth Brody wrote:
>>>>> i = (i, i++, i) + i;

|________| |
| |
A B

> Why? The left hand expression in brackets is a sequence of
> expressions. The i++ MUST be evaluated before the last one or it makes
> a mockery of the entire reason for sequence points IMO.


But which subexpression will be evaluated first, A or B? C99 6.5p3 says
it's unspecified for operands of +.

-Beej

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: subexpressions (OT: math) Steve Howell Python 23 06-04-2007 11:49 AM
subexpressions Sergey Dorofeev Python 20 06-04-2007 12:35 AM
Re: subexpressions Steve Howell Python 2 06-02-2007 02:39 PM
Examples of using "reluctant" subexpressions in regexps? david.karr@wamu.net Java 4 04-27-2005 07:46 PM
pre_match and post_match for subexpressions trans. (T. Onoma) Ruby 0 10-24-2004 03:41 AM



Advertisments