Sequence point.

S

somenath

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 ?
 
E

Eric Sosman

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.

Try this modified program; perhaps it will help you understand:

#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;
}
 
W

williamjohn.gowers

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.
 
E

Eric Sosman

^^^ ^^^

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.
 
J

James Kuyper

^^^ ^^^

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.
 
S

somenath

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.



Try this modified program; perhaps it will help you understand:



#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.
 
M

Malcolm McLean

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.
 
E

Eric Sosman

[...]
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.
 
S

Seebs

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
 
S

Seebs

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
 
K

Keith Thompson

Seebs said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top