confused with operators ++ --

Pages: 12
I made this program as my c++ homework

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main()
{ 
int a=15, b=3;
a= a*6/a++;
b= --b*a++/b;
cout << "a=" << a << endl;
cout << "b=" << b << endl; 

cin.get();

return 0;
}


but now i have to also resolve the problems on paper.

i thought i undersand how to handle the operators ++ -- as sufix and prefix yet i don't know how to use it here.
1
2
3
int a=15, b=3;
a= a*6/a++;
b= --b*a++/b;


in exercise a should i add 1 to (a=15) before dividing or after or what should i do ?
i tried

a= 15*6/15+1
a= 90/15+1
a= 6+1
a= 7

but when i run the program the answer is 8 so i know i'm doing it wrong.

in the other problem

b= --b*a++/b;
i thought
b= (3-1)*15+1/3

but as i failed in the first exercise i assume i'm wrong in this one too.

i read and understand how the operators ++ -- can be used as prefix and as a suffix

but only in exercises like the example:
example 1
1
2
3
4

b=3;
a=++b
// a contains 4, b contains 4 

example 2
1
2
3
4
5

b=3;
a=b++;
//a contains 3, b contains 4

B is increased before its value is copied to A. While in Example 2, the value of B is copied to A and then B is increased.


could someone please explain me more in depth so i can solve my exercises

thanks in advance

PS. i searched before asking but all the examples i found are similar to the one i pasted here.

Last edited on
closed account (zb0S216C)
Kronolynx wrote:
a= a*6/a++;

The order of evaluation is undefined. This means the computation can take any of these forms:

1) (a * 6) / a++
2) (a * (6 / a++))

As Bjarne Stroustrup said: "When in doubt, parenthesise." Parenthesis' are used in expressions to change the order of evaluation. In the first form above, a is multiplied by 6 before dividing the result by a++. In second form above, 6 is divided by a++ before multiplying the result by a. See how the order changed?

Wazzak
Last edited on
thanks framework i understand what you say and appreciate your help. my problem is that i was given exactly like below and i have to work with it like that.
int a=15, b=3;
a= a*6/a++;
b= --b*a++/b;


when i run the program it gives me the answers as
a=8
b=7


and when i try to solve it on paper i don't know how to do it. i try to solve it but i get diffent result, in a i get 7 instead of 8

how should i do it ?

thanks again
@Framework

a= a*6/a++;

The order of evaluation is undefined. This means the computation can take any of these forms:

1) (a * 6) / a++
2) (a * (6 / a++))


It is invalid statement. The order of evaluaition is defined and corresponds to

1) a++
2) a * 6
3) ( a * 6 ) / ( a++ )

The problem is that the expression a= a*6/a++; has undefined behavior according to the C++ Standard. There is no sequence point between the assignment to a and applying of the side effect of the postincrement operaor.
closed account (zb0S216C)
vlad from moscow wrote:
"It is invalid statement. The order of evaluaition is defined"

No, it's not. Why? Because the compiler can apply optimisations to the expression for better usage of the ALU.

Wazzak
The compiler may apply optiomization but it shall not change observable behavior!
Last edited on
closed account (zb0S216C)
True, but expressions such as the ones above have no defined order of evaluation. Thus, the result can be anything. That's why people use parenthesis' to define the order.

Wazzak
No, you are wrong. The expression has defined order of evaluation according priorities of operators and orders of execution of operators with the same priority. The postincrement operator in this expression has the highest priotity. All other operators with the same priority are executed from left to right. If, for example, there would be two assignment operators in the expression they were executed from right to left.
Last edited on
1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
void main()
{
 int a=2;
 int b=5;
int c=0;
c=--a*b++/b;
printf("%d",c);
}

1
2
3
4
Output:
1 
exp:
c=--a*b++/b;

Thumb Rule:
1.operations are done as per precedence of operators in expression.
2.If there are multiple operators in expression with same precedence, they are eveluated in the order of their occurence from left to right.
so:
all operatore -- * / ++ have same precedence
c=--a:1 step1
c=1*b++: 1*5++ step 2 5++ will be done after evaluation of entire expression.
c=5/b :5/5 step3
c=1
@anirudh sn
all operatore -- * / ++ have same precedence


Again you are wrong. For example the postincrement operator ++ has higher priority than the preincrement operator ++.
Last edited on
closed account (zb0S216C)
You do know the evaluation order of both postfix and prefix increment/decrement operators is undefined, right?

Wazzak
@Framework
You do know the evaluation order of both postfix and prefix increment/decrement operators is undefined, right?


If you ask me then I will say no, I do not know this. Postfix operators have higher priority than prefix operators according to the C/C++ standard.

From the C++ Standard

5.2 Postfix expressions
...
postfix-expression ++
postfix-expression --


5.3 Unary expressions [expr.unary]
1 Expressions with unary operators group right-to-left.
unary-expression:
postfix-expression
++ cast-expression
-- cast-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-id )
sizeof ... ( identifier )
alignof ( type-id )
noexcept-expression
new-expression
delete-expression
unary-operator: one of
* & + - ! ~
Last edited on
vlad is 100% correct.

The operator precedence is clearly defined.

In this code:
c=--a*b++/b;

1) "b++" has highest precedence
2) then "--a"
3) * and / have equal precedence, and will be evaluated left to right.
4) lastly, = has the lowest precedence.

Therefore the above statement is the same as:

c = ( ( (--a) * (b++) ) / b );

HOWEVER, the result of this is still undefined because b is being read and written within the same sequence point.

Operator precedence only dictates the order in which expressions must be evaluated in relationship to each other. It does not dictate the order in which two separate and unrelated expressions must be evaluated.

So if b=5 going into the above statement, the / b at the end might be / 5 or it might be / 6. This kind of code must always be avoided!
@andirun sn

if i understand you right it would be like this ?

a= a*6/a++;
a= 15*6/15++
a= 90 / 15
a= 6


b= --b*a++/b;
b= --3*15++/3
b= 2*15++/3
b= 30/3
b= 10


but when i run the program the answers i get are

a=8
b=7


thanks again for all the answers
@vlad: you are absolutely right, but since post increment is done after evaluation of expression with original value, it doesnt matter right.
anyways, i have to correct my earlier statement.
All operators in expression are of different precedence.
1
2
3
4
5
6
7
8
9
#include<stdio.h>
void main()
{
 int a=2;
 int b=5;
int c=0;
c=--a*b++/b;
printf("%d",c);
}

exp:
c=--a*b++/b;

step1:b++ result seen after evaluation of complete exopression
step2:--a :1
step3:* and / have same precedence evaluate from left to right in order they appear
--a*b(original value) 1*5=5
step 4:
--a*b(original value)/b(original value): 5/5
Result=1.
Thumb rules:
1.operations are done as per precedence of operators in expression.
2.If there are multiple operators in expression with same precedence, they are eveluated in the order of their occurence from left to right.
anirudh sn wrote:
Result=1.


No, the result is undefined. The flaw in your logic is in step 4:


step 4:
--a*b(original value)/b(original value): 5/5


That 2nd 'b' may or may not be the original value. It may be the incremented value. This behavior is not defined by the C++ standard and you must never do this in actual code.


EDIT: To clarify further...

For purposes of this example, let's simplify the expression to isolate the parts we're interested in:

1
2
b = 1;
c = b++ / b;


Operator precedence rules dictate that ++ will be evaluated before /. This is guaranteed. What isn't dictated is the order of the expressions around the / in relationship to each other.

That is, there are two smaller expressions here: b++ and b. Both must be fully evaluated before the division operator is evaluated.

But in which order are they evaluated? It isn't specified... so it's undefined.

The compiler might evaluate b first, resulting in c=2. Or it might evaluate the b++ first, resulting in c=0.

Or it might evaluate part of b++ first, then b, then finish evaluating the incrementing part of b++, resulting in c=1

Or it might do something completely different, resulting in any number of possible outcomes.
Last edited on
Perhaps it's helpful to show by example.

Ignoring for the moment that the program is invalid (due to UB, twice!) and compiling it is meaningless, I'm going to compile the original program and run it on a few platforms

linux/gcc: a=8 b=7
linux/clang: a=6 b=8
linux/icc: a=7 b=9
aix/xlc: a=8 b=7
sparc/sun studio: a=7 b=6
hpux/acc: a=7 b=6


GNU GCC and HP aCC issued compiler diagnostics for both erroneous lines (a= a*6/a++; and b= --b*a++/b;)


PS: there is some confusion in this thread regarding order of evaluation vs. operator precedence. Operator precedence is a grammar rule, it tells how to parse an expression, not how to evaluate it.
Last edited on
@dish i did the example you made and the result is 1

i have been playing around with the compiler and the numbers i was given

i found out that if i have:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int main()
{ 
int a=15, b=3, c=0 ;

a= a*6/a++;
cout << "a=" << a << endl; 
cout << "b=" << b << endl;
cout << "c=" << c << endl;


cin.get();

return 0;
}

the answer i get is 7



but if i change the a in the problem to c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int main()
{ 
int a=15, b=3, c=0 ;

c= a*6/a++;
cout << "a=" << a << endl; 
cout << "b=" << b << endl;
cout << "c=" << c << endl;


cin.get();

return 0;
}


the answer i get is 6


then i tried to test in different ways
i separated both exercises and run them

based on the answers i got from the program

it would be something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int a=15, b=3, c=0, d=0;
c= a*6/a++;
d= --b*a++/b;


c=a*6/a++  // a++ remains as it was, no addition is made
c=15*6/15
c=90/15
c=6

d= --b*a++/b   // --b decreases by 1 and also modifies the next b
d= 2*15/2
d= 30/2
d=15


which are the right answers

then i tried putting everything in the same program like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int main()
{ 
int a=15, b=3, c=0, d=0;
c= a*6/a++;
d= --b*a++/b;
cout << "a=" << a << endl;
cout << "b=" << b << endl; 
cout << "c=" << c << endl;
cout << "d=" << d << endl;

cin.get();

return 0;
}


then the answers change but only in the answer for d which is not anymore 15 it changes to 16 while the answer for c remains 6.

so i guess that

1
2
c= a*6/a++;  // the a++ that was not evaluated here 
d= --b*a++/b; // is enforced here even though it still ignores the a++ from this line 

so things are like this:

1
2
3
4
5
d= --b*a++/b   
d= 2*16/2     // the 1 added is not from the a++ but from the previous a++ from c
d= 32/2
d=16


my conclusion is that only the prefix is evalutated while the suffix is ignored but enforced in the next line modifying our value . so if we had a third line
e=a
the value of e in that line would be 17 instead of our original 15

i tried here
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

int main()
{ 
int a=15, b=3, c=0, d=0, e=0;
c= a*6/a++;
d= --b*a++/b;
e= a;
cout << "a=" << a << endl;
cout << "b=" << b << endl; 
cout << "c=" << c << endl;
cout << "d=" << d << endl;
cout << "e=" << e << endl;

cin.get();

return 0;
}


and this are the values i got

1
2
3
4
5
a=17
b=2
c=6
d=16
e=17
Last edited on
@dish i did the example you made and the result is 1


The whole point is that the language does not define proper behavior here, so it is impossible to reliably anticipate the outcome.

Testing and saying "when I tried it I got this" is pointless because someone else might get something completely different when they try it. It might vary depending on what version of what compiler you're using and what optimization settings are configured, the phase of the moon, etc, etc, etc.

You are trying to find a pattern where there isn't one. Trying to find predictability where there is none. You should stop... it's a wasted effort.

my conclusion is that only the prefix is evalutated while the suffix is ignored but enforced in the next line modifying our value


Your conclusion is wrong. You are only analyzing how your compiler with your settings is building this particular piece of code. That says absolutely nothing about how the C++ language operates.
Last edited on
@dish I'm just starting to learn c++ so as i couldn't get a straight answer which i needed for my homework, i tested and tried to find my own answers, it may be a waste of time but i had fun doing it. it satisfied my curiosity for knowing how my compiler behaves in these cases.

:)

also i didn't know that each compiler behaves different.

thanks to everyone for trying to help.
Last edited on
Pages: 12