Is there a sequence point between these assignments?
Asked Answered
C

6

15

Is there a sequence point between the two assignments in the following code:

f(f(x=1,1),x=2);
Candlewood answered 9/9, 2011 at 2:34 Comment(0)
U
3

The relevant quote from the (draft) standard [6.5.2.2, 10] is:

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

So for your expression, the first argument (in particular the call to f) could be evaluated before the second argument; e.g.:

(x = 1, 1), f <sp> call, (x = 2), f <sp> call

Or, it could be evaluated after the second argument; e.g.:

(x = 2), (x = 1, 1), f <sp> call, f <sp> call

[The function call itself can (and most probably will) contain more sequence points (in particular if it contains a return statement).]

Depending on that, there is a sequence point between the assignments or not. It is up to the platform ("unspecified").

Since in the 2nd case, you are assigning to x twice between two sequence points, you have undefined behaviour on such a platform.

Unsung answered 27/9, 2011 at 11:12 Comment(0)
C
5

No there isn't. The standard is indeed ambiguous in this case.

If you want to confirm that, gcc has this really cool option -Wsequence-point and in this case it will warn you that the operation may be undefined

Coxalgia answered 9/9, 2011 at 2:42 Comment(11)
I've gotten false positives from that option before (for strtol(s++, &s, 0), though it was fixed in later gcc versions) so I'm hesitant to rely on it.Candlewood
@R. I agree in general, but in this particular case there is no sequence point.Coxalgia
Although (according to you) the standard is ambiguous, (at least in gcc) the arguments of a function are evaluated from right to left. The reason is obvious, in C, the arguments are pushed on the stack from right to left, so why would the compiler evaluate them from left to right and reserve their place and store them ahead of their place in the stack? I'm quite certain there isn't a compiler foolish enough to evaluate from left to right.Lovettalovich
@Lovettalovich the question is about the standard. Compilers are free to interpret the standard as they see fit. It has nothing to do with how arguments are pushed on the stack. Your argument is also flawed. To give you an example, try x=2; f(x, x=1). Even though the x=1 is to the right of the original x, the function call is f(1,1)Coxalgia
@Foo bah. I know and I said, despite the fact that it's not standard, it's how it's done. Besides, what you said proves my point not contradict it! Like I said, arguments are evaluated from right to left so in your example, x=1 is evaluated first and hence the f(1,1). Maybe read my previous comment again.Lovettalovich
@Lovettalovich f(x=1,x) does the same thingCoxalgia
@foo bah, I just tested f(x=1, x) on my g++, the result was f(1, 2). It would have been really really odd if both of them did the same thing. I mean, whether left-to-right or right-to-left, both of them CAN'T have the same results!Lovettalovich
@Lovettalovich G++ is a C++ compiler, and the rules there are very different. You should read the specification, it is a bit more specific in this area. In gcc [the C frontend, note that the question focused on C] you should get f(1,1) for both cases.Coxalgia
Just because it's warning about undefined behaviour in an expression this does not mean that the expression lacks sequence points.Chuckchuckfull
@Chuckchuckfull it's the value of x that is underdetermined in this code block. There are circumstances where the lack of specificity here is irrelevant (for example, if the expression were f(f(x=1,1),y=2);, it wouldn't matter if y=2 occurs before or after the x=1).Coxalgia
@FooBah yeah I understand that.Chuckchuckfull
C
3

There are sequence points at the beginning of a function call and at it's end. However because the order of operations on function arguments is implementation defined you can't gaurantee that f(x=1,1) will be executed before x=2.

Also note that the , in the function call case is not the comma operator that introduces a sequence point.

Chuckchuckfull answered 27/9, 2011 at 8:27 Comment(0)
U
3

The relevant quote from the (draft) standard [6.5.2.2, 10] is:

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

So for your expression, the first argument (in particular the call to f) could be evaluated before the second argument; e.g.:

(x = 1, 1), f <sp> call, (x = 2), f <sp> call

Or, it could be evaluated after the second argument; e.g.:

(x = 2), (x = 1, 1), f <sp> call, f <sp> call

[The function call itself can (and most probably will) contain more sequence points (in particular if it contains a return statement).]

Depending on that, there is a sequence point between the assignments or not. It is up to the platform ("unspecified").

Since in the 2nd case, you are assigning to x twice between two sequence points, you have undefined behaviour on such a platform.

Unsung answered 27/9, 2011 at 11:12 Comment(0)
C
0

There is a sequence point, but the order of evaluation (and their side effects) of the outer function's arguments is still undefined. The implementation is free to first evaluate the inner f(), with its side effect x=1, or the second argument with its side effect x=2.

Curule answered 9/9, 2011 at 10:31 Comment(3)
@R. I think wildplasser is saying there is a sequence point right before the inner function is evaluated but no sequence point that forces one of the assignments to be performed before the other.Coxalgia
I agree there's a sequence point before the inner function is called (after its arguments are evaluated), but as far as I can tell there's no sequencing that prevents the second assignment from happening before the arguments to the inner function call are evaluated...Candlewood
After reading (and rereading) Seth's quote, I change my mind. There is no obligation for the implementation to evaluate all the function arguments at once; if we summarize the fragment as "f( f(a,b),c)", then any order of evaluation of {a,b,c} is allowed before the intervening sequencepoint(s) of calling f() have happened.Curule
C
-3

Yes, because there is a sequence point before and after function calls.

§1.0.17 of the Standard says:

When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function).

Cabdriver answered 9/9, 2011 at 2:36 Comment(6)
But we don't know which argument to the outer f is evaluated first.Euphorbia
But why couldn't both be evaluated before either function call takes place? In that case, there seems to be no sequence point...Candlewood
@R..: There is by definition a sequence point. The Standard has spoken.Maltase
@Jeremy you are assuming that the inner function argument must be evaluated first, but that's not guaranteed by the wording of the standard.Coxalgia
But there's no sequence point before evaluating the arguments. So it seems possible to me that all of the arguments are evaluated before any of the function calls. Is this reasoning invalid?Candlewood
@Foo Bah: I originally read the question as, "Is there a sequence point?" and didn't see the part about the two assignments. But even then, the answer is that there must be two sequence points between if the implementation chooses to evaluate the entire subcall argument before the bare assignment argument, and there is not one if it chooses another order. So the only possible answer seems to be "maybe".Maltase
A
-4

Yes there will be a sequence point due to comma operatror But still result will be undefined as evaluation of function arguments is undefined so can't predict what value this expression will generate........means undefined behaviour

Attested answered 27/9, 2011 at 8:21 Comment(1)
There is no comma operator. The comma separates arguments in a function call.Cyndicyndia

© 2022 - 2024 — McMap. All rights reserved.