I've noticed in a few discussions recently that the phrase "sequence
point" keeps popping up.
Alas I (and no-one else here) has any idea what it means.
Can someone please give me a simple definition?
Cheers in advance, Argos
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
> I've noticed in a few discussions recently that the phrase "sequence
> point" keeps popping up.
>
> Alas I (and no-one else here) has any idea what it means.
>
> Can someone please give me a simple definition?
>From the C++ Standard, 1.9/7:
... Evaluation of an expression might produce side effects. 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.
--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ Time is a storm in which we are all lost.
\__/ George Bernard Shaw
Alcyone Systems' CatCam / http://www.catcam.com/
What do your pets do all day while you're at work? Find out.
Argos wrote:
> I've noticed in a few discussions recently that the phrase "sequence
> point" keeps popping up.
>
> Alas I (and no-one else here) has any idea what it means.
>
> Can someone please give me a simple definition?
I'd suggest you go back to the answer we provided to this very
question about two weeks ago in DejaNews, but Google has destroyed
DEJA and replaced it with their own ususable system (not invented
here sickness to the extreme).
A sequence point is defined in the C++ language as a point where
variables are in a known state, and all side effects are complete.
In general, order of operations in C++ is arbitrary:
f() + g() + j++;
You don't know if f() is executed before g() or after, or when the ++
is applied to j. All you know is that everything has been done when
the sequence point occurs.
Where are sequence points?
1. There is a sequence point at the end of each full expression (an
expression
not a part of any other). You can think of this as being at the ";" in
the
above statement.
2. There is a sequence point at the beginning (after the arguments are
evaluated)
and end of subroutines. Note that this one is slightly problematic
because
for example in the above example, even though a sequence point occurs
around the
execution of f(), you still don't know if it did g() first, etc....
3. There is a sequence point after the evaluation of the first operand of
a few "special" operators, notably the built-in comma, &&, ||, and ?:
operators.
In addition to putting things in a known state, the language puts some
specific
restrictions on the programmer. A variable may only be changed once between
sequence points:
k = x++ + x++;
is undefined behavior (the compiler need not do anything specific nor even
compile
the above expression).
Furthermore, if you change the value, you're not supposed to use it for
anythign else
inside the expression:
k = i++ + i;
Careful with your phrasing! Remember that you're explaining to
someone what sequence points are about... :-)
The value of a variable that is changed by can not be used until
the next occurence of a sequence point -- not "inside the
expression," as you said. The expression may involve sequence
points, as you mentioned previously in your message:
bool k = i++ > 0 || i > b;
Is perfectly valid, nad you're using i in the same expression
where a side effect took place.
Carlos
--
PS: I know you knew this one -- the only thing I'm pointing
out is that your phrasing may be confusing, given that
it is addressed to someone that is trying to understand
the sequence points.
> The value of a variable that is changed by can not be used until
> the next occurence of a sequence point -- not "inside the
> expression," as you said. The expression may involve sequence
> points, as you mentioned previously in your message:
>
> bool k = i++ > 0 || i > b;
>
> Is perfectly valid, nad you're using i in the same expression
> where a side effect took place.
I thought the standard allowed the different sides of the '||' to
be evaluated in any order. Is that incorrect, are you guaranteed
left-to-right execution of something like this?
In practice, I often do:
{
Something* s;
Compute(s);
if ((s != NULL) && (s.someState))
{
//...
}
}
...but always thought that the order of evaluation COULD be
right-to-left...
-tom!
--
Tom Plunket to...@fancy.org
PlayStation2/3D Studio geek
Change is inevitable. Progress is not.
Ah, there we go - 5.15/1 "Unlike |, || guantees left-to-right evaluation.
Moreover, the second operand is not evaluated if the first operand evaluates
to true"
And similar for && in 5.14/1
So boolean short-circuiting *is* guarenteed.
Ric
5.14 Logical AND operator
"The && operator groups letf-to-right...Unlike &, &&
guarantees left-to-right evaluation: the second operand
is not evaluated if the first operand is false."
Similar rule for the || and conditional operator in 5.15
and 5.16. The || doesn't evaluate the second operand if the
first is true, and the conditional only evaluates one of
the second and third expressions.
Even that is less than what is required. The left-hand side must be
fully evaluated and all side effects complete before the rhs is even
considered. The rhs MUST NOT be evaluated unless the result is needed
to determine the boolean value of the complete expression. Of course
this is entirely different for user provided overloads of those
operators:)
--
Francis Glassborow
See http://www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)
The standard guarantees that the above does exactly what you assume it does.
The term used for this in Stroustrup's book is 'short-circuit evaluation',
and it wouldn't work if && didn't introduce a sequence point.
(It's weird; most of the C and C++ code I write would break instantly if
this rule didn't apply, and still several experienced programmers I know are
not familiar with it. Like you, they use it, but are not convinced that
it's supposed to work. :-)
/Jorgen
--
// Jorgen Grahn <jgrahn@ ''Battle ye not with monsters,
\X/ algonet.se> lest ye become a monster''
Tom Plunket wrote:
>
> I thought the standard allowed the different sides of the '||' to
> be evaluated in any order. Is that incorrect, are you guaranteed
> left-to-right execution of something like this?
For the built-in ||, certainly NOT! The left side of || is ALWAYS
executed first. A sequence point then occurs, then if the left side
is FALSE, the right side is executed.
This is why it's exteremely bogus to overload operator||. The overloaded
operator|| behaves like a regular function call (unspecified order and
both sides are always executed).
>
> In practice, I often do:
>
> {
> Something* s;
> Compute(s);
>
> if ((s != NULL) && (s.someState))
> {
> //...
> }
> }
>
> ...but always thought that the order of evaluation COULD be
> right-to-left...
>
Hopefully you meant s->someState (otherwise it won't compile).
If you thought that the order was arbitrary, and that short circuiting
didn't occur, why would you do such a thing? You'd be dereferencing
a null poitner.
Whoa! no! If that was true, then how would you guarantee shortcut
evaluation? Also, how could it make sense that || introduces a
sequence point if the expression may be evaluated in any order??
What would be the role of the sequence point in such case?
> In practice, I often do:
>
> {
> Something* s;
> Compute(s);
>
> if ((s != NULL) && (s.someState))
I'll assume you meant s->someState
> ...but always thought that the order of evaluation COULD be
> right-to-left...
If the compiler were allowed to evaluate that in any order,
then your code would be severely broken -- you might be
dereferencing a NULL pointer, and only at the marcy of the
compiler! :-)
Cheers,
Carlos
--
Tom Plunket wrote:
>
>
> ...but always thought that the order of evaluation COULD be
> right-to-left...
>
> -tom!
No. The language garantees short circuit evaluation from left to right.
That is why it is not well advised to overload &&, ||, and ,. When these
are functions, they dont behave as their operator counterpart.
Claude
--
Claude Quézel (claude...@syntell.corba)
anti-spam: replace corba by com in private replies
"Accessing an object designated by a volatile lvalue (_basic.lval_),
modifying an object, calling a library I/O function, or calling a
function that does any of those operations are all side effects, which
are changes in the state of the execution environment. Evaluation of
an expression might produce side effects. 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 subse-
quent evaluations shall have taken place.5)
> I thought the standard allowed the different sides of the '||'
to
> be evaluated in any order. Is that incorrect, are you
guaranteed
> left-to-right execution of something like this?
>
> In practice, I often do:
>
> if ((s != NULL) && (s.someState))
>
> ...but always thought that the order of evaluation COULD be
> right-to-left...
If you thought the evaluation could be right-to-left, how did you
think this idiom could possibly be safe?
(Of course, as written, it won't compile if s is a pointer. Maybe
that's what makes it safe?)
--
末Thomas Paul Diffenbach
reply to t...@diffenbach.org
I realized, so suddenly and so forcefully that it cannot but be
true: there are no epiphanies.
> Tom Plunket writes
>
> >I thought the standard allowed the different sides of the '||' to
> >be evaluated in any order. Is that incorrect, are you guaranteed
> >left-to-right execution of something like this?
> >
Francis Glassborow wrote:
> Even that is less than what is required. The left-hand side must be
> fully evaluated and all side effects complete before the rhs is even
> considered. The rhs MUST NOT be evaluated unless the result is needed
> to determine the boolean value of the complete expression. Of course
> this is entirely different for user provided overloads of those
> operators:)
Thank you- this is what I was looking for. Not a discussion
about "if you can't guarantee it, why do you do it?" I mean,
it's not as if I didn't say explicitly that "in practice this is
the way it works," or anything. Sheesh, you people sometimes...
-tom!
--
Tom Plunket to...@fancy.org
PlayStation2/3D Studio geek
What do you mean, it doesn't work? It worked fine yesterday...
Well, our messages were, in a sense, elaborating a bit more in
what you were saying, rather than simply pointing out the rules.
If you can't accept corrections and take offense by anyone pointing
out something wrong in what you said, maybe this is the wrong place
for you to be... Also, you simply can not expect that every single
individual in here replies to you in the exact way and telling you
*exactly* what you expect. Different people notices different
details and react differently. Please don't feel offended or
bothered by that. It's the variety of points of views what makes
this an interesting place to be!
As an example, check my posts in the past three or four days.
You'll see that John "nit picked" on me (according to your standards)
like, a million times... Well, even though they were obvious
oversights when I was writing them, it's always good to point out
the errors, in case other people (less skilled, maybe) are confused
or misled by the errors.
Sure, that doesn't mean that John, or someone else, is going to
say or suggest that I have no idea what I'm talking about, that I
should take a beginner's book and learn some C++ before posting, or
any other kind of rude comments! They probably see (as we did with
your message) that it was an obvious oversight, a distraction...
Still, it's worth pointing out the detail, as long as it is done
in a respectful way (which I believe we all did when replying
to your message).
Cheers,
Carlos
--