I don't understand why this function is equal to 1

Pages: 12
I'm new to C++ and I can't seem to understand why the following function is equal to 1:

1
2
3
4
5
6
#include <iostream>
int main(){

    int x =7;
    std::cout << (++x <= 9 && x + 2 >= 10); //1
}


Based on what I learned about the concepts of operators (operator precedence, evaluation order and short circuiting) the result should be `0`. here is what I think it should be:

1
2
3
4
5
int x =7;
std::cout << (8 <= 9 && 9 >= 10);

//In other words:
std::cout << (True && False); //False = 0 


Can someone please tell me why it's equal to 1 ?!
x + 2 is 10.
Thanks Peter.
But x is 7 and 7+2 = 9. can you please tell me why it's 10 ?

I also tried a simpler function like:
1
2
int x = 3;
std::cout << (x == ++x); //1 


x is 3 and ++x is 4.
3 is not equal to 4.

how can it be "true" ?!
when x + 2 is evaluated, x = 8. The first condition is

 
++x <= 9


x is 7 - but this first increments x (pre-increment - ++) making x = 8. 8 is less-or-equal to 9, so true.

For the second condition which is only evaluated if the first is true:

 
x + 2 >= 10


x is now 8. 8 + 2 is greater-or-equal to 10 - so true.

As both conditions are true, the result of the && (logical and) is true so cout displays 1 (for true).

 
std::cout << (x == ++x);


This looks like UB (undefined behaviour) as the same variable is used more than once and it is also changed within the same expression.

If a side effect on a memory location is unsequenced relative to a value computation using the value of any object in the same memory location, the behavior is undefined.

 
n = ++i + i;      // undefined behavior 



See https://en.cppreference.com/w/cpp/language/eval_order#Undefined_behavior

Lets look at one possible evaluation:

 
(x == ++x)


let x be 3.

First evaluate ++x. This gives 4 and sets the value of x to 4

Then evaluate x. This is now 4.

So the condition is 4 == 4 which is true!
Last edited on
The left side of && is evaluated first. ++x increments the value of x so that its value becomes 8.
So when the right side of && is evaluated x+2 will evaluate to 10 because x is 8 at that point.
I believe the following code leads to undefined behaviour (UB).

 
std::cout << (x == ++x); //1 

I'm pretty sure but not 100% because there has been some updates to these rules in recent versions of C++ and it's hard to keep track of everything. GCC (with -Wall) warns about it.

GCC wrote:
test.cpp:5:20: warning: operation on 'x' may be undefined [-Wsequence-point]
    5 | std::cout << (x == ++x); //1
      |                    ^~~

To put it simply, you're generally not allowed to use the same variable multiple times in the same expression if the variable is also modified at the same time. There are some exceptions. It's not a problem with && and || because the left side is guaranteed to be evaluated (and all side-effects to take place) before the right side starts being evaluated.

https://en.cppreference.com/w/cpp/language/eval_order#Undefined_behavior
Last edited on
std::cout << (x == ++x); is well defined after C++17.

C++17 introduced a sequenced before rule for operators << and >>.

AFAIK, x == ++x was well defined even before C++17, though the GNU compiler does warn about it.
x == ++x was well defined even before C++17


Is this because all side-effects are first evaluated before the comparison? Is there a standard reference for this?
This is from the current draft standard:
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand.
https://eel.is/c++draft/expr.ass#1


ISO/IEC 14882:2011 did not have this: The right operand is sequenced before the left operand.
The rest of it is unchanged.
Clang also warns.

I don't think the << and >> operators are relevant for this particular example. The question is whether the first operand to == is sequenced before the second operand. I don't think that is the case.

It is the case with the = operator.
The right operand is sequenced before the left operand.
https://eel.is/c++draft/expr.ass#1

But I don't see a similar wording for the == operator.
https://eel.is/c++draft/expr.eq
Last edited on
> I don't see a similar wording for the == operator

I'm sorry, I misread the == as = (even after copy pasting it twice).

The GNU compiler had warned even for x = ++x: http://coliru.stacked-crooked.com/a/ab64240ea2eea0bd
CodeMode, don't be confused by all this. I don't think you need to know these rules in detail (evidently not even we do). They are complicated and change in different versions of C++. Just avoid writing confusing expressions that modifies data in the middle of expressions, especially if the same data is also read elsewhere in the same expression, and you'll be fine most of the time.

Instead of
 
std::cout << (++x <= 9 && x + 2 >= 10);
write
1
2
++x;
std::cout << (x <= 9 && x + 2 >= 10);
or
1
2
++x;
std::cout << (x <= 9 && x >= 8);
or
1
2
++x;
std::cout << (x == 8 || x == 9);


Last edited on
Thank you so much seeplus and Peter for your detailed answer

Aaaah.. NOW I know where I went wrong Peter. the procedure is similar to this:

1
2
 int x = 7;
    std::cout << ++x << " " << x + 2; //8  10 (the next expression is dependent on the previous one) 


But I never thought it would be the same in an && condition and the tutorial that I was watching was doing it all with two variables like this:

1
2
3
int x = 7;
int y = 5;
    std::cout << (++x <= 9 && y + 2 >= 10); //0 


Now that I think about it, it was really hard for a beginner like me to figure it out.


But as for the:
std::cout << (x == ++x); //1

well I'm using the latest version of Microsoft Visual Studio 17.2.6 and it works with no error. but you're right here on this website it throws the UB error

I don't know. you guys are pros and you know it absolutely better.

Thanks again
CodeMode wrote:
I'm using the latest version of Microsoft Visual Studio 17.2.6 and it works with no error. but you're right here on this website it throws the UB error

Undefined behaviour just means the C++ standard doesn't specify what will happen. Compilers might show a warning if they detect it but there is no requirement to do so.
With VS2022 (latest), both of these output 1 (true) with no warnings (level 4 set):

1
2
3
4
5
6
7
8
#include <iostream>

int main() {
	int x = 3;

	std::cout << (++x == x) << '\n';
	std::cout << (x == ++x) << '\n';
}


so I still suspect that side-effects are evaluated first.

To me, this is one of those 'dark corners' of C++ that are best not disturbed. When writing code, just don't use side-effects (ie ++) on the same variable used elsewhere in the same expression.

Even if a compiler gives one result now, it doesn't necessarily follow that you'll get the same result with future versions. Sequencing (which is the issue here) has changed in previous c++ standards.

Bottom line: don't do this in production code!
Last edited on
This website uses at best a C++14 compiler. There were sequencing changes in C++17 - maybe that's why online is reporting an UB (but shows the same true true result) and VS2022 is not???

I try to avoid these 'dark corners'...
CodeMode wrote:
I never thought it would be the same in an && condition

You do realize that ++x is not a shortcut for x+1, do you? (This is a quite common mistake by beginners)

Instead it is a shortcut for x += 1 (or x = x + 1). In other words, it increases the value of x by one.

It doesn't matter in what context it's used. When evaluated it always modifies x.
Last edited on
1
2
3
int x = 7;
int y = 5;
    std::cout << (++x <= 9 && y + 2 >= 10); //0  


There's no issue here - as different variables are used. Most of the above discussion is when the same variable is used with at least one side-effect.
In other words, it increases the value of x by one.


and returns the incremented value. This is called pre-inc.

As opposed to:

 
x++;


which also increases the value of x by 1 but returns the value as it was before the increment. This is called post-inc

Mixing up these 2 is also a common beginner mistake.

NB The same for --x and x-- but dec rather than inc.

For more info see:

https://www.learncpp.com/cpp-tutorial/increment-decrement-operators-and-side-effects/

Last edited on
You do realize that ++x is not a shortcut for x+1, do you?

Well before you explain everything in detail:
https://cplusplus.com/forum/beginner/284503/#msg1232157

I had the same concept on my mind! I thought ++x <= 9 is x+1 <=9 and it's only related to this expression. but it's funny because I had already learned how pre-post increments worked. here is a good example from the link seeplus provided:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main()
{
    int x{ 5 };
    int y{ 5 };
    std::cout << x << ' ' << y << '\n'; //5 5
    std::cout << ++x << ' ' << --y << '\n'; // 6 4
    std::cout << x << ' ' << y << '\n'; // 6 4
    std::cout << x++ << ' ' << y-- << '\n'; // 6 4
    std::cout << x << ' ' << y << '\n'; // 7 3

    return 0;
}


Just like the example, I thought incs/decs would only work for Bitwise operators and each cout expression can only have one variable of the same type. that's why I got confused when it came to logical operators that check whether an expression is true or false

And btw you gave another example in one of your previous posts that either I missed or you edited your post later. You said:
Instead of
 
std::cout << (++x <= 9 && x + 2 >= 10);


write
1
2
++x;
std::cout << (x <= 9 && x + 2 >= 10);


It was a very good example and I fully understood what you meant by that but is it the same case for suffix as well ? I mean what if it's x++ ? then the result will be completely different right ? take this new one as an example:

1
2
x = 7;
std::cout << (x++ == 7 && x + 2 >= 10); //1 (7 == 7 && 8 + 2 >= 10) 


1
2
3
x = 7;
x++; //or ++x
std::cout << (x == 7 && x + 2 >= 10); //0 (8 == 7 && 8 + 2 >= 10) 



For more info see:
https://www.learncpp.com/cpp-tutorial/increment-decrement-operators-and-side-effects/


I was in the middle of learning C++ through YouTube courses (beginner to advanced) and I thought it would have been easier to learn things visually. maybe it wasn't a good idea because I think they might miss some important programming tips and I might end up asking such questions.

The link that you provided, on the other hand, is great. I think I should start learning from here:
https://www.learncpp.com/cpp-tutorial

Thanks again guys and I'm gonna mark this topic as solved
Pages: 12