why "++a" is undefined behaviour ?

A

arnuld

my friend sent me this programme:

#include<iostream>
int main()
{
int a=5;
std ::cout << ++a
<< "\t"
<< ++a
<<

return 0;
}

its output should be "6 7" and this i what i get:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new2.cpp
new2.cpp: In function 'int main()':
new2.cpp:10: warning: operation on 'a' may be undefined
(arnuld@arch ~ )% ./a.out
7 7
(arnuld@arch ~ )%


to not to relay on "undefined behaviuor" i changed this programme:

#include<iostream>

int
main()
{
int a =
5;

int b = +
+a;
int c = +
+a;

std::cout <<
b
<<
"\t"
<<
c
<<
std::endl;

return
0;
}


and now it runs as expected:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new.cpp
(arnuld@arch ~ )% ./a.out
6 7
(arnuld@arch ~ )%


i want to know why the direct use of ++a in std::cout is undefiend
behaviour" ?
 
G

gara.matt

my friend sent me this programme:

#include<iostream>
int main()
{
int a=5;
std ::cout << ++a
<< "\t"
<< ++a
<<

return 0;

}

its output should be "6 7" and this i what i get:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new2.cpp
new2.cpp: In function 'int main()':
new2.cpp:10: warning: operation on 'a' may be undefined
(arnuld@arch ~ )% ./a.out
7 7
(arnuld@arch ~ )%

to not to relay on "undefined behaviuor" i changed this programme:

#include<iostream>

int
main()
{
int a =
5;

int b = +
+a;
int c = +
+a;

std::cout <<
b
<<
"\t"
<<
c
<<
std::endl;

return
0;

}

and now it runs as expected:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new.cpp
(arnuld@arch ~ )% ./a.out
6 7
(arnuld@arch ~ )%

i want to know why the direct use of ++a in std::cout is undefiend
behaviour" ?

It isn't. You can use ++a directly in your cout statement. If you take
a closer look, your first post didn't have "<< endl;" or a semicolon
at all which is what caused it.
 
S

szclark

my friend sent me this programme:

#include<iostream>
int main()
{
int a=5;
std ::cout << ++a
<< "\t"
<< ++a
<<

return 0;

}

its output should be "6 7" and this i what i get:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new2.cpp
new2.cpp: In function 'int main()':
new2.cpp:10: warning: operation on 'a' may be undefined
(arnuld@arch ~ )% ./a.out
7 7
(arnuld@arch ~ )%

to not to relay on "undefined behaviuor" i changed this programme:

#include<iostream>

int
main()
{
int a =
5;

int b = +
+a;
int c = +
+a;

std::cout <<
b
<<
"\t"
<<
c
<<
std::endl;

return
0;

}

and now it runs as expected:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new.cpp
(arnuld@arch ~ )% ./a.out
6 7
(arnuld@arch ~ )%

i want to know why the direct use of ++a in std::cout is undefiend
behaviour" ?

Hi, I think it might have been down to the fact that you did not
include an endl; statement or even just a ;

#include<iostream>
int main()
{
int a = 5;
std ::cout << ++a << "\t;
std ::cout << ++a;
return 0;
}

This returned 6 7.

Hope that helped.
 
A

arnuld

Hi, I think it might have been down to the fact that you did not
include an endl; statement or even just a ;

#include<iostream>
int main()
{
int a = 5;
std ::cout << ++a << "\t;
std ::cout << ++a;
return 0;

}

This returned 6 7.

you introduced an extra statement in the programme for producing the
correct result. why i can not get the same output using one single
statement ?
 
S

szclark

you introduced an extra statement in the programme for producing the
correct result. why i can not get the same output using one single
statement ?

I think this is because the compiler will increment 'a' twice before
the line is output to the screen, so the output will then be 7 7.
 
J

Jim Langston

I think this is because the compiler will increment 'a' twice before
the line is output to the screen, so the output will then be 7 7.

There is no sequence point between the ++a. The compiler is free to
evaulaute things in any order between sequence points. The new statement
introduces a sequence point, which is why you get the expected result with 2
statements.

Read the FAQ, 39.15 and 39.16.
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.15
 
M

Michael DOUBEZ

Jim Langston a écrit :
There is no sequence point between the ++a. The compiler is free to
evaulaute things in any order between sequence points. The new statement
introduces a sequence point, which is why you get the expected result with 2
statements.

Read the FAQ, 39.15 and 39.16.
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.15

Yes. But in this case, you can be tempted to think the expression
evaluates to:
cout.operator<<(++a).operator<<("\t").operator<<(++a).operator<<(std::endl);
Where you can think there is a sequence point at each member function
call and parameters are evaluated in order.

It seems to be clearer (IMVHO :) ) with:
operator<<(
operator<<(
operator<<(
operator<<(cout,++a),
"\t"),
++a),
std::endl);
Where one can see it is free to evaluate the second ++a before the first
because there is no order of evaluation.
Therefore, the output can be
7 6
or
6 7

I am not sure how you can end up with 7 7 since there is a sequence
point between each function call.


Michael
 
M

Michael DOUBEZ

Michael DOUBEZ a écrit :
Jim Langston a écrit :


Yes. But in this case, you can be tempted to think the expression
evaluates to:
cout.operator<<(++a).operator<<("\t").operator<<(++a).operator<<(std::endl);

Where you can think there is a sequence point at each member function
call and parameters are evaluated in order.

It seems to be clearer (IMVHO :) ) with:
operator<<(
operator<<(
operator<<(
operator<<(cout,++a),
"\t"),
++a),
std::endl);
Where one can see it is free to evaluate the second ++a before the first
because there is no order of evaluation.

On parameters of course.
 
A

arnuld

Yes. But in this case, you can be tempted to think the expression evaluates to:
cout.operator<<(++a).operator<<("\t").operator<<(++a).operator<<(std::endl);
Where you can think there is a sequence point at each member function
call and parameters are evaluated in order.
It seems to be clearer (IMVHO :) ) with:
operator<<(
operator<<(
operator<<(
operator<<(cout,++a),
"\t"),
++a),
std::endl);
Where one can see it is free to evaluate the second ++a before the first
because there is no order of evaluation.

well, as a beginning C++ Programmer that is far beyond my
understanding.
Therefore, the output can be
7 6
or
6 7

I am not sure how you can end up with 7 7 since there is a sequence
point between each function call.

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new.cpp
new.cpp: In function 'int main()':
new.cpp:10: warning: operation on 'a' may be undefined
(arnuld@arch ~ )% ./a.out
7 7
(arnuld@arch ~ )% g++ --version
g++ (GCC) 4.2.1 20070704 (prerelease)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

(arnuld@arch ~ )%
 
A

anon

arnuld said:
my friend sent me this programme:

#include<iostream>
int main()
{
int a=5;
std ::cout << ++a
<< "\t"
<< ++a
<<

return 0;
}

So, this is only one statement:

std::cout << ++a << "\t" << ++a << std::endl;

therefore a is incremented twice before anything is done (ie. something
is printed to standard output).

That means you got the correct output.

I can not back this up with a chapter number from the standard as I do
not have it, but this is how c++ works with prefix increment operator
i want to know why the direct use of ++a in std::cout is undefiend
behaviour" ?

IMO undefined behavior is something different, not this
 
A

anon

arnuld said:
my friend sent me this programme:

#include<iostream>
int main()
{
int a=5;
std ::cout << ++a
<< "\t"
<< ++a
<<

return 0;
}

its output should be "6 7" and this i what i get:

(arnuld@arch ~ )% g++ -ansi -pedantic -Wall -Wextra new2.cpp
new2.cpp: In function 'int main()':
new2.cpp:10: warning: operation on 'a' may be undefined
(arnuld@arch ~ )% ./a.out
7 7
(arnuld@arch ~ )%

Basically the rule in C is that if you have an expression, and somewhere
in that expression, you use an increment operator on a variable, you
can't mention that variable elsewhere in the expression.

If we ignore this, then you got correct values (a is incremented twice,
and then printed)
 
A

arnuld

So, this is only one statement:
std::cout << ++a << "\t" << ++a << std::endl;
therefore a is incremented twice before anything is done (ie. something
is printed to standard output).
That means you got the correct output.

and i thought this works like this:

1.) std::cout << ++a << "\t" << ++a << std::endl;

2.) (std::cout << ++a) << "\t" << ++a << std::endl;

3.) (std::cout << ++a) returns std::cout as a result and as a side-
effect it writes the vale of "++a" (== 6) to the the standard output,
which in this case is my terminal. (from C++ Primer 4/e, section
chapter 1, 1.2.2)


4.) (std::cout << "\t") << ++a << std::endl;

same as step 3

5.) (std::cout << ++a) << std::endl;

same as step 3 and this time ++a will be printed (== 7)

6.) std::cout << std::endl;

this will produce a newline and will flush the buffer


where i am wrong ?

I can not back this up with a chapter number from the standard as I do
not have it, but this is how c++ works with prefix increment operator

you can but i trust your information as GCC agrees with you :)

IMO undefined behavior is something different, not this

ouch!
 
J

James Kanze

Jim Langston a écrit :

More precisely, any attempt to modify an object twice without
an intervening sequence point, or to access an object which is
modified other than to determine its new value, is undefined
behavior. The compiler can assume that you don't do it, and
optimize in consequence.

As to the reasons: the only one is "because the standard says
so". It's been the rule since the early days of C, and we've
not progressed since then.
Yes. But in this case, you can be tempted to think the expression
evaluates to:
cout.operator<<(++a).operator<<("\t").operator<<(++a).operator<<(std::endl);

Actually, it's a bit more complicated, because the operator<<
for char const* is a non-member. So you end up with:

operator<<(
operator<<( cout.operator<<( ++a ),
"\t" )
.operator<<( ++a ),
std::endl ) ;

Not that it matters. In this respect, a.op<<( b ) behaves
exactly like op<<( a, b ).
Where you can think there is a sequence point at each member function
call and parameters are evaluated in order.

There is a sequence point at each function call, and at each
return. But sequence points don't define a complete ordering,
and there's no ordering between the various sub-expressions.
It seems to be clearer (IMVHO :) ) with:
operator<<(
operator<<(
operator<<(
operator<<(cout,++a),
"\t"),
++a),
std::endl);
Where one can see it is free to evaluate the second ++a before the first
because there is no order of evaluation.

Member or free functions don't change anything.
Therefore, the output can be
7 6
or
6 7
I am not sure how you can end up with 7 7 since there is a sequence
point between each function call.

But that only creates a partial ordering. Consider a somewhat
simpler example, numbering the various operations:

operator<<( // 1
operator<<( // 2
cout, // 3
++ a ), // 4
++ a ) ; // 5

The function calls are 1 and 2. Since each function provides an
operand for the next, they must be ordered: 2 must occur before
1. Similarly, 4 must occur before 2, and 5 must occur before 1.
(The fact that the function calls are sequence points means that
the side effects must also occur. Or rather, they mean that
anytime you can establish an ordering requirement which involves
as sequence point, you can modify the same object both before
and after the sequence point.) But those are the only constraits
on order. You'll notice that there are no ordering constraints
between 4 and 5. A compiler can evaluate in the order 5, 4, 3,
2, 1, for example. (In fact, this is probably the easiest order
for a machine using a memory based stack which grows down. Like
an Intel.)

As soon as any legal ordering involves modifying an object
twice, without an intervening sequence point, you have undefined
behavior.
 
J

James Kanze

So, this is only one statement:
std::cout << ++a << "\t" << ++a << std::endl;
therefore a is incremented twice before anything is done (ie. something
is printed to standard output).

No. a is modified twice without an intervening sequence point.
So the behavior is undefined.
That means you got the correct output.
I can not back this up with a chapter number from the standard
as I do not have it, but this is how c++ works with prefix
increment operator

Not necessarily. The above code has undefined behavior, so
anything might happen.
IMO undefined behavior is something different, not this

The standard is very clear about this. You modify the same
object twice. For certain legal orders of evaluation, there is
no intervening sequence point (i.e. function call, end of full
expression, etc.). Thus, the behavior is undefined.
(Interestingly, the latest draft of the standard seems to have
stricken this text. Can it be that we're going to get defined
behavior here?)

There are very, very few operators which impose order: &&, ||,
?: and the comma operator come to mind. In addition, although
the standard doesn't really say so directly, there is cause and
effect: the operands of an operator must be evaluated before the
operator is evaluated. Still, in an expression like the above,
that leaves any number of legal orderings, including some which
increment a twice without an intervening function call (which
would introduce a sequence point).

Note that ordering is a separate issue from associativity. In
an expression like "x+y+z", the compiler must execute the
addition in "x+y" before it executes the second addition (or at
least have the same observable behavior as if it did). On the
other hand, it can evaluate the sub-expressions x, y and z in
any order, and even mix them, evaluating part of x, then doing
part of z, etc.
 
A

anon

arnuld said:
and i thought this works like this:

1.) std::cout << ++a << "\t" << ++a << std::endl;

2.) (std::cout << ++a) << "\t" << ++a << std::endl;

3.) (std::cout << ++a) returns std::cout as a result and as a side-
effect it writes the vale of "++a" (== 6) to the the standard output,
which in this case is my terminal. (from C++ Primer 4/e, section
chapter 1, 1.2.2)


4.) (std::cout << "\t") << ++a << std::endl;

same as step 3

5.) (std::cout << ++a) << std::endl;

same as step 3 and this time ++a will be printed (== 7)

6.) std::cout << std::endl;

this will produce a newline and will flush the buffer


where i am wrong ?

Steps 3 and 4 are executed simultaneously, that is is incremented twice,
before it is sent to the standard output
you can but i trust your information as GCC agrees with you :)



ouch!

I tried to cancel this message, but looks like it did not work ;)

And you get that warning only with -Wall. But I would rather change the
code, then remove that parameter
 
P

Pete Becker

The standard is very clear about this. You modify the same
object twice. For certain legal orders of evaluation, there is
no intervening sequence point (i.e. function call, end of full
expression, etc.). Thus, the behavior is undefined.
(Interestingly, the latest draft of the standard seems to have
stricken this text. Can it be that we're going to get defined
behavior here?)

No. Sequence points have been replaced by the notions of "sequenced
before", "indeterminately sequenced", etc. (See [intro.execution]/14,
for example). This was done through N2239, with the assurance that this
is a new form of description with no semantic changes. The new form of
description is intended to make it easier to specify the behavior of
multi-threaded programs.
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,228
Latest member
MikeMichal

Latest Threads

Top