Connecting Tech Pros Worldwide Help | Site Map

About comma expression.

PengYu.UT@gmail.com
Guest
 
Posts: n/a
#1: Dec 1 '05
I used comma expression in two different ways in the following code.
This code is reduced from some more complex code. I don't have the
ability to write in the 2nd way for the complex code.

I want the output of the 2nd is wanted. Do you have any idea how to
modify the 1st way such that it gives the same output as the 2nd one?

Thanks,
Peng

#include <iostream>

class plot {
public:
plot &doit(int &i){
std::cout << i << std::endl;
return *this;
}
};

int main ()
{
plot p;
int i = 10;
p.doit((++i,i)).doit((++i,i));// output 12 12; 1st way; not wanted
std::cout << std::endl;
i = 10;
p.doit((++i,i));
p.doit((++i,i)); // output 11 12; 2nd way different from above
}

n2xssvv g02gfr12930
Guest
 
Posts: n/a
#2: Dec 1 '05

re: About comma expression.


PengYu.UT@gmail.com wrote:[color=blue]
> I used comma expression in two different ways in the following code.
> This code is reduced from some more complex code. I don't have the
> ability to write in the 2nd way for the complex code.
>
> I want the output of the 2nd is wanted. Do you have any idea how to
> modify the 1st way such that it gives the same output as the 2nd one?
>
> Thanks,
> Peng
>
> #include <iostream>
>
> class plot {
> public:
> plot &doit(int &i){
> std::cout << i << std::endl;
> return *this;
> }[/color]
plot &incdoit(int &i)
{
++i;
doit(i);
}[color=blue]
> };
>
> int main ()
> {
> plot p;
> int i = 10;
> p.doit((++i,i)).doit((++i,i));// output 12 12; 1st way; not wanted
> std::cout << std::endl;
> i = 10;
> p.doit((++i,i));
> p.doit((++i,i)); // output 11 12; 2nd way different from above[/color]
std::cout << std::endl;
i = 10;
p.incdoit(i).incdoit(i); // output 11,12[color=blue]
> }
>[/color]
Using preincrement of a variable more than once in an expression results
in unpredictable behaviour, because it is compiler dependent.
To get round this without changing plot::doit() I suggest the changes
shown.

JB
deane_gavin@hotmail.com
Guest
 
Posts: n/a
#3: Dec 1 '05

re: About comma expression.



PengYu.UT@gmail.com wrote:[color=blue]
> I used comma expression in two different ways in the following code.
> This code is reduced from some more complex code. I don't have the
> ability to write in the 2nd way for the complex code.
>
> I want the output of the 2nd is wanted. Do you have any idea how to
> modify the 1st way such that it gives the same output as the 2nd one?
>
> Thanks,
> Peng
>
> #include <iostream>
>
> class plot {
> public:
> plot &doit(int &i){
> std::cout << i << std::endl;
> return *this;
> }
> };
>
> int main ()
> {
> plot p;
> int i = 10;
> p.doit((++i,i)).doit((++i,i));// output 12 12; 1st way; not wanted
> std::cout << std::endl;
> i = 10;
> p.doit((++i,i));
> p.doit((++i,i)); // output 11 12; 2nd way different from above
> }[/color]

Have a look at this

http://www.gotw.ca/gotw/056.htm

If you imagine

p.doit((++i,i)).doit((++i,i));

as the compiler sees it (like a normal function, with the object's this
pointer passed as an extra parameter) you get

doit( &(doit(&p, (++i, i))), (++i, i) );

I think that, despite your use of the comma operator to introduce a
sequence point between ++i and i each time, the fact that the
evaluation of function arguments can happen in any order and can be
interleaved means that you still have undefined behaviour. The second
++i can start before the first one has finished.

http://www.parashift.com/c++-faq-lit...html#faq-39.15

I have stared at your code for quite a while and I'm not 100% sure of
my answer. If I'm wrong, hopefully someone will correct me.

Gavin Deane

Ron Natalie
Guest
 
Posts: n/a
#4: Dec 1 '05

re: About comma expression.


n2xssvv g02gfr12930 wrote:
[color=blue][color=green]
>> p.doit((++i,i));
>> p.doit((++i,i)); // output 11 12; 2nd way different from above[/color][/color]
[color=blue][color=green]
>>[/color]
> Using preincrement of a variable more than once in an expression results
> in unpredictable behaviour, because it is compiler dependent.[/color]

Not in this case. Comma operator enforces both an ordering and a
sequence point. The left side is FULLY evaluated, and a sequence
point occurs before the right side is evaluated.
Ron Natalie
Guest
 
Posts: n/a
#5: Dec 1 '05

re: About comma expression.


PengYu.UT@gmail.com wrote:
[color=blue]
> p.doit((++i,i)).doit((++i,i));// output 12 12; 1st way; not wanted
>[/color]
In this case the compiler is allowed to do both the left sides of
the comma operators before doing the sequence point and the right
side. This is undefined behavior.
deane_gavin@hotmail.com
Guest
 
Posts: n/a
#6: Dec 1 '05

re: About comma expression.



Ron Natalie wrote:[color=blue]
> PengYu.UT@gmail.com wrote:
>[color=green]
> > p.doit((++i,i)).doit((++i,i));// output 12 12; 1st way; not wanted
> >[/color]
> In this case the compiler is allowed to do both the left sides of
> the comma operators before doing the sequence point and the right
> side. This is undefined behavior.[/color]

I posted a similar answer, though I wasn't entirely confident I was
right. It's good to see some confirmation. I have another question now.
Can the compiler stop *between* completing the evaluation of ++i and
"doing" the sequence point. I thought would be

start evaluating ++i
finish evaluating ++i // implies sequence point happens

The problem would then arise if we started to evaluate the second ++i
before we had finished evaluating the first one. But then if ++i is a
single machine instruction (which I imagine it would be) then the
compiler couldn't stop part way through evaluating it (this is why I
wasn't 100% sure of my answer to the OP).

You seem to suggest the problem is actually

completely evaluate first ++i
do sequence point for the comma operator

and clearly the nasal demons are summoned if the second ++i is
evaluated between those two steps.

Is my understanding of what you have said correct?

Thanks
Gavin Deane

Ron Natalie
Guest
 
Posts: n/a
#7: Dec 1 '05

re: About comma expression.


deane_gavin@hotmail.com wrote:[color=blue]
> Ron Natalie wrote:[color=green]
>> PengYu.UT@gmail.com wrote:
>>[color=darkred]
>>> p.doit((++i,i)).doit((++i,i));// output 12 12; 1st way; not wanted
>>>[/color]
>> In this case the compiler is allowed to do both the left sides of
>> the comma operators before doing the sequence point and the right
>> side. This is undefined behavior.[/color]
>
> I posted a similar answer, though I wasn't entirely confident I was
> right. It's good to see some confirmation. I have another question now.
> Can the compiler stop *between* completing the evaluation of ++i and
> "doing" the sequence point. I thought would be
>
> start evaluating ++i
> finish evaluating ++i // implies sequence point happens
>[/color]
There is no "finish" of a side effect until a sequence point.
If there are two modifications of the same variable happening
for a an allowable ordering before the sequence point, then
you have a problem.

Whether you have interleaved instructions or the subexpressions are
executed in different processors in parallel.
n2xssvv g02gfr12930
Guest
 
Posts: n/a
#8: Dec 1 '05

re: About comma expression.


Ron Natalie wrote:[color=blue]
> n2xssvv g02gfr12930 wrote:
>[color=green][color=darkred]
>>> p.doit((++i,i));
>>> p.doit((++i,i)); // output 11 12; 2nd way different from above[/color][/color]
>
>[color=green][color=darkred]
>>>[/color]
>> Using preincrement of a variable more than once in an expression
>> results in unpredictable behaviour, because it is compiler dependent.[/color]
>
>
> Not in this case. Comma operator enforces both an ordering and a
> sequence point. The left side is FULLY evaluated, and a sequence
> point occurs before the right side is evaluated.[/color]
Granted for the comma operators, but these could still be evaluated
before the member function calls, (as actually happened). Personally I
much prefer code that doesn't require such a detailed knowledge of
sequence points, as that is prone to errors both during bug fixing and
development, (this case demonstrates the point). Maybe that's the half
decent engineer in me that prefers to reduce risk created by potential
doubt.

JB
Closed Thread


Similar C / C++ bytes