2

I understand the basic differences between prefix/postfix notation for decrement/increment operators in C++. However, there is something going on in the next example that stumps me.

The code I shared below prints the following.

5*4**3***4****2*****1

But I would have guessed it would print this.

5*4**4***3****2*****1

How is this happening? Is something going on with pushing/popping to/from the stack?

int var = 5;
cout << var-- << '*'; //prints 5 and then decrements to 4.
cout << var << "**"; //The value of var (now 4) 
                     //is printed to the console.
//The next line prints 3***4****.
//I would have guessed it prints  4***3****.
cout << var-- << "***" << var-- << "****";  
//No matter what the above line prints, 
//the value of var after the above lines is 2, so...
cout << var-- << "*****" << var << endl; //...Print 2, decrement to 1 
                                         //and then 1 is finally printed.
AbdelAziz AbdelLatef
  • 3,650
  • 6
  • 24
  • 52
krsju
  • 21
  • 3
  • I'm using Visual Studio 2019 on a Windows 10 laptop...Several of my students got the same result as me as well. Any ideas anyone? – krsju Oct 15 '19 at 23:25
  • 1
    @krsju Take care with the warning messages: http://coliru.stacked-crooked.com/a/22eda0ae6e1f21d9 and https://en.cppreference.com/w/cpp/language/eval_order – Amadeus Oct 15 '19 at 23:27
  • Warning messages: The first line of defense against logic errors. Ignore at your own risk. – user4581301 Oct 15 '19 at 23:28
  • ```g++-9.2 -Wall -pedantic test.cpp``` gives this warning: ```warning: operation on ‘var’ may be undefined [-Wsequence-point]``` with the above code. – neutrino_logic Oct 15 '19 at 23:45

2 Answers2

1

Welcome to the strange world of undefined behaviour. Calling an increment or decrement operator twice on the same variable, in the same statement, is undefined behaviour, so don't do it :)

#include <iostream>

int main()
{
  int i = 1;
  // should this print 9, 10, or 12? Compilers will vary... 
  std::cout << (++i + ++i + ++i) << std::endl;
  return 0;
}
robthebloke
  • 9,331
  • 9
  • 12
  • I think this one changed in C++17. [Here's cppreference's take on it.](https://en.cppreference.com/w/cpp/language/eval_order#Sequenced-before_rules_.28since_C.2B.2B11.29) – user4581301 Oct 15 '19 at 23:30
  • Whether it's ever allowed or not, it's never going to be readable (or maintainable) code imho. – robthebloke Oct 15 '19 at 23:31
  • That I'll agree with. – user4581301 Oct 15 '19 at 23:33
  • Thank you for your help. I am just surprised because this example came from a brand new famous author's textbook. I would have thought the text would either warn about this issue or not asked students to predict output related to undefined behaviour. – krsju Oct 16 '19 at 00:08
0

The problem in this line:

cout << var-- << "***" << var-- << "****";

is undefined behaviour because you using post-decrement twice in a single statement.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54