# Sequence point.

Discussion in 'C Programming' started by somenath, Sep 30, 2013.

1. ### somenathGuest

I am not able to understand why the following program output as follows.

#include<stdio.h>
void test(int x,int y)
{
printf("x = %d\n",x);
printf("y = %d\n",y);

}

int main(void)
{
int i =5;
int j =5;
test(++i,j++);

return 0;
}

\$ ./a.exe
x = 6
y = 5

According to my understanding function call provide sequence point i.e all the side effect will be guaranteed to be complete ( after the evaluation of all the arguments, and just before the actual cal).
so in case of j++ the value of the expression is j but as a side effect j gets incremented by 1. So test will receive the value 6,6.
Where am I going wrong here ?

somenath, Sep 30, 2013

2. ### Eric SosmanGuest

On 9/30/2013 11:17 AM, somenath wrote:
> I am not able to understand why the following program output as follows.
>
> #include<stdio.h>
> void test(int x,int y)
> {
> printf("x = %d\n",x);
> printf("y = %d\n",y);
>
> }
>
>
> int main(void)
> {
> int i =5;
> int j =5;
> test(++i,j++);
>
> return 0;
> }
>
> \$ ./a.exe
> x = 6
> y = 5
>
> According to my understanding function call provide sequence point i.e all the side effect will be guaranteed to be complete ( after the evaluation of all the arguments, and just before the actual cal).
> so in case of j++ the value of the expression is j but as a side effect j gets incremented by 1. So test will receive the value 6,6.
> Where am I going wrong here ?

The test() function prints the values x,y -- not the values i,j.
The expression `++i' adds 1 to `i' and yields the new value; that is
the value that `x' receives. The expression `j++' adds 1 to `j' and
yields the original value; that original value is what `y' receives.
At the point of the printf() calls, then, `x' is 6 and `y' is 5. As
it happens, both `i' and `j' are now 6, but they're not what test()
prints.

#include <stdio.h>
int i = 5; // formerly in main(), now at file scope
int j = 5; // ditto

void test(int x, int y) {
printf("x = %d, y = %d\n", x, y);
printf("i = %d, j = %d\n", i, j);
}

int main(void) {
test(++i, j++);
return 0;
}

--
Eric Sosman
d

Eric Sosman, Sep 30, 2013

3. ### Guest

On Monday, September 30, 2013 3:17:14 PM UTC, somenath wrote:
> I am not able to understand why the following program output as follows.
>
>
>
> #include<stdio.h>
>
> void test(int x,int y)
>
> {
>
> printf("x = %d\n",x);
>
> printf("y = %d\n",y);
>
>
>
> }
>
>
>
>
>
> int main(void)
>
> {
>
> int i =5;
>
> int j =5;
>
> test(++i,j++);
>
>
>
> return 0;
>
> }
>
>
>
> \$ ./a.exe
>
> x = 6
>
> y = 5
>
>
>
> According to my understanding function call provide sequence point i.e all the side effect will be guaranteed to be complete ( after the evaluation of all the arguments, and just before the actual cal).
>
> so in case of j++ the value of the expression is j but as a side effect jgets incremented by 1. So test will receive the value 6,6.
>
> Where am I going wrong here ?

From http://en.cppreference.com/w/cpp/language/operator_incdec :

pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.

post-increment and post-decrement creates a copy of the object, increments or decrements the value of the object and returns the copy from before the increment or decrement.

So when you type `j++`, the compiler interprets that as: create a copy of j, then increment the original j, and then pass in the value of the copy to the function. These are the 'side effects' you allude to, and they do indeed all complete before the function call. This is the easiest way to get as close as possible to our intuition - that j++ means 'do all the things toj, and then increment j'.

It would also be a lot less useful if test(i, j++) and test(i, ++j) did thesame thing.

, Sep 30, 2013
4. ### Eric SosmanGuest

On 9/30/2013 11:28 AM, wrote:
> [...]
> From http://en.cppreference.com/w/cpp/language/operator_incdec :

^^^ ^^^

Wrong language. C and C++ are not the same.

> pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.

No: Both operators yield the *value* (pre- or post-) of the object.
Neither yields a reference; C does not have references.

> post-increment and post-decrement creates a copy of the object, increments or decrements the value of the object and returns the copy from before the increment or decrement.

No: Neither operator copies an object, nor does either yield
a copied object.

> So when you type `j++`, the compiler interprets that as: create a copy of j,

No.

> then increment the original j, and then pass in the value of the copy

No.

> It would also be a lot less useful if test(i, j++) and test(i, ++j) did the same thing.

Here, you're right.

--
Eric Sosman
d

Eric Sosman, Sep 30, 2013
5. ### James KuyperGuest

On 09/30/2013 11:38 AM, Eric Sosman wrote:
> On 9/30/2013 11:28 AM, wrote:
>> [...]
>> From http://en.cppreference.com/w/cpp/language/operator_incdec :

> ^^^ ^^^
>
> Wrong language. C and C++ are not the same.
>
>> pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.

>
> No: Both operators yield the *value* (pre- or post-) of the object.
> Neither yields a reference; C does not have references.

Not to disagree with you, but simply to clarify:
Even though C and C++ are not, in general, the same, and even though C
does not have references, both languages handle the relevant aspects of
++ and -- the same.
C++ operator overloads for those operators are typically written in the
manner he describes, and C++ handles overload resolution using the
concept of operator overload functions for built-in type which have the
same type of function signature. However, those functions don't have to
actually exist, the concept that they do is just a convenient way to
organize overload resolution so it handles built-in types in a way
that's consistent with the way it handles user-defined types. The
description of how the increment and decrement operators actually work
for built-in types is very similar to the corresponding section of the C
standard, and makes no mention of those overloads.

James Kuyper, Sep 30, 2013
6. ### somenathGuest

On Monday, September 30, 2013 8:54:54 PM UTC+5:30, Eric Sosman wrote:
> On 9/30/2013 11:17 AM, somenath wrote:
>
> > I am not able to understand why the following program output as follows.

>
> >

>
> > #include<stdio.h>

>
> > void test(int x,int y)

>
> > {

>
> > printf("x = %d\n",x);

>
> > printf("y = %d\n",y);

>
> >

>
> > }

>
> >

>
> >

>
> > int main(void)

>
> > {

>
> > int i =5;

>
> > int j =5;

>
> > test(++i,j++);

>
> >

>
> > return 0;

>
> > }

>
> >

>
> > \$ ./a.exe

>
> > x = 6

>
> > y = 5

>
> >

>
> > According to my understanding function call provide sequence point i.e all the side effect will be guaranteed to be complete ( after the evaluation of all the arguments, and just before the actual cal).

>
> > so in case of j++ the value of the expression is j but as a side effect j gets incremented by 1. So test will receive the value 6,6.

>
> > Where am I going wrong here ?

>
>
>
> The test() function prints the values x,y -- not the values i,j.
>
> The expression `++i' adds 1 to `i' and yields the new value; that is
>
> the value that `x' receives. The expression `j++' adds 1 to `j' and
>
> yields the original value; that original value is what `y' receives.
>
> At the point of the printf() calls, then, `x' is 6 and `y' is 5. As
>
> it happens, both `i' and `j' are now 6, but they're not what test()
>
> prints.
>
>
>
>
>
>
> #include <stdio.h>
>
> int i = 5; // formerly in main(), now at file scope
>
> int j = 5; // ditto
>
>
>
> void test(int x, int y) {
>
> printf("x = %d, y = %d\n", x, y);
>
> printf("i = %d, j = %d\n", i, j);
>
> }
>
>
>
> int main(void) {
>
> test(++i, j++);
>
> return 0;
>
> }
>
>
>

Thanks for the explanation. I missed the point that the value of the argument is passed to the function.

So the value of the expression j++ is 5 but the value of j is 6 and the value of the expression that is 5 is passed to the function.

somenath, Sep 30, 2013
7. ### Malcolm McLeanGuest

On Monday, September 30, 2013 4:17:14 PM UTC+1, somenath wrote:
> I am not able to understand why the following program output as follows.
>
> test(++i,j++);
>

The ++ operator is a bit confusing.

In most of mathematics, precedence refers to binding as well as to order
of application. So if we say x = 1 + 2 *3, we apply the 2*3 first, yielding
six, then add one to it, to give 7.
However if in C we write int i = 3; x = 1 + 2 *i++; then the ++ is applied to
the i only, but only after everything else has been evaluated. So x is still
7, but i is 4.
It's a little quirk that takes a bit of getting used to, but in fact it makes
programs easier to write.

Malcolm McLean, Sep 30, 2013
8. ### Eric SosmanGuest

On 9/30/2013 12:34 PM, somenath wrote:
> On Monday, September 30, 2013 8:54:54 PM UTC+5:30, Eric Sosman wrote:
>> On 9/30/2013 11:17 AM, somenath wrote:
>>> [...]
>>> int main(void)
>>> {
>>> int i =5;
>>> int j =5;
>>> test(++i,j++);
>>> [...]

> Thanks for the explanation. I missed the point that the value of the argument is passed to the function.
>
> So the value of the expression j++ is 5 but the value of j is 6 and the value of the expression that is 5 is passed to the function.

Right. One tiny elaboration: The value of `j' *after the
sequence point* is 6.

--
Eric Sosman
d

Eric Sosman, Sep 30, 2013
9. ### SeebsGuest

On 2013-09-30, somenath <> wrote:
> I am not able to understand why the following program output as follows.

> #include<stdio.h>
> void test(int x,int y)
> {
> printf("x = %d\n",x);
> printf("y = %d\n",y);
>
> }

> int main(void)
> {
> int i =5;
> int j =5;
> test(++i,j++);
>
> return 0;
> }

> \$ ./a.exe
> x = 6
> y = 5

Looks right to me.

> According to my understanding function call provide sequence point i.e all the side effect will be guaranteed to be complete ( after the evaluation of all the arguments, and just before the actual cal).
> so in case of j++ the value of the expression is j but as a side effect j gets incremented by 1. So test will receive the value 6,6.
> Where am I going wrong here ?

You are misunderstanding "j++". The value of the expression is not "the
variable j", it is "the value the variable j had before this operator came
into play".

Imagine it as being roughly like this:

int postinc(int *x) {
int old = *x;
*x = *x + 1;
return old;
}
int preinc(int *x) {
int new;
*x = *x + 1;
new = *x;
return new;
}

The value "old" in the postinc function isn't going to change it's value just
because you *later* modified *x.

The entire point of postincrement is to yield the value j *used to have*. If
sequence points changed its behavior, it would be useless.

-s
--
Copyright 2013, all wrongs reversed. Peter Seebach /
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
Autism Speaks does not speak for me. http://autisticadvocacy.org/
I am not speaking for my employer, although they do rent some of my opinions.

Seebs, Oct 1, 2013
10. ### SeebsGuest

On 2013-09-30, Malcolm McLean <> wrote:
> On Monday, September 30, 2013 4:17:14 PM UTC+1, somenath wrote:
>> I am not able to understand why the following program output as follows.
>>
>> test(++i,j++);
>>

> The ++ operator is a bit confusing.
>
> In most of mathematics, precedence refers to binding as well as to order
> of application. So if we say x = 1 + 2 *3, we apply the 2*3 first, yielding
> six, then add one to it, to give 7.
> However if in C we write int i = 3; x = 1 + 2 *i++; then the ++ is applied to
> the i only, but only after everything else has been evaluated. So x is still
> 7, but i is 4.
> It's a little quirk that takes a bit of getting used to, but in fact it makes
> programs easier to write.

I don't think it's true that it's "only after everything else has
been evaluated". The compiler is welcome to, if it really wants,
increment i before it does anything else in the expression, as long
as it still uses the value 3.

Order of evaluation and binding are logically distinct in C. If you write:
a() + b() * c()
the compiler is welcome to emit the three function calls in any order, as
long as the result is computed by multiplying the results of b and c together,
then adding that to the result of a.

-s
--
Copyright 2013, all wrongs reversed. Peter Seebach /
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
Autism Speaks does not speak for me. http://autisticadvocacy.org/
I am not speaking for my employer, although they do rent some of my opinions.

Seebs, Oct 1, 2013
11. ### Keith ThompsonGuest

Seebs <> writes:
[...]
> You are misunderstanding "j++". The value of the expression is not
> "the variable j", it is "the value the variable j had before this
> operator came into play".
>
> Imagine it as being roughly like this:
>
> int postinc(int *x) {
> int old = *x;
> *x = *x + 1;
> return old;
> }
> int preinc(int *x) {
> int new;
> *x = *x + 1;
> new = *x;
> return new;
> }
>
> The value "old" in the postinc function isn't going to change it's
> value just because you *later* modified *x.
>
> The entire point of postincrement is to yield the value j *used to
> have*. If sequence points changed its behavior, it would be useless.

Right.

The expression `j++` *could* be implemented as the equivalent of
(j = j + 1, j - 1). The side effect of incrementing j can occur
any time between the previous and next sequence point, as long as
the value yielded by j++ is as specified.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Oct 1, 2013