1

Decrementation / Incrementation is a basic operation but it's precendence on - -- and + ++ confused me. I'll use decrementation for illustration:

I have a set here of different styles of operating between a and b: See it working here

#include <iostream>
using namespace std;
int a=10, b=7;
int main() {
// - and -- opearator                         // Results:  Details:
    a = 10, b = 7; cout << a---b << endl;     //    3      a post-decrement        
    a = 10, b = 7; cout << a ---b << endl;    //    3      a post-decrement     
    a = 10, b = 7; cout << a- --b << endl;    //    4      b pre-decrement    
    a = 10, b = 7; cout << a-- -b << endl;    //    3      a post-decrement  
    a = 10, b = 7; cout << a--- b << endl;    //    3      a post-decrement 
    return 0;
    }

I understand that the 4 output came from the decremented b which is 7 that turned to 6 and is subtracted from a which is 10.

Also, because of the other four statements, I thought the compiler treats all of them as --- but behold, here comes the confusion of - -- results. See it working here

Aesthetic
  • 763
  • 1
  • 14
  • 31
  • 6
    All the bits in the "Details after a statement" column are wrong. All of those decrement exactly one variable. –  Mar 03 '14 at 12:30
  • Try putting the operations in its own statement so the prefix/postfix doesn't confuse the results. E.g. `auto const x = a---b; std::cout << x << ", " << a << ", " << b << "\n";` – dyp Mar 03 '14 at 12:32
  • 1
    Also see the "goes toward" operator, [`-->`](http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator). – molbdnilo Mar 03 '14 at 12:37
  • @hvd I mean Results I got from echo – Aesthetic Mar 03 '14 at 12:39
  • 1
    The linked examples repeatedly print out the value of `a` while labeling it as "`b`". If you fix it so that it actually prints out the value of `b` you'll see that nothing is particularly surprising or confusing about the program's behaviour, and there's no difference between parsing of `-` and `+`. – Weeble Mar 03 '14 at 13:56

5 Answers5

10

Parsing follows the maximal munch rule, so all statements minus the third are interpreted as (a--)-b which decrements a and returns its previous value (which was 10).

The third one is a-(--b) which is a pre-decrement on b, so the new decremented value is returned.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
2

But why didn't it decremented after it's statement?

Because the --X operator:

  • first performs the decrement
  • then returns the result of decrementing

So, there's no way that --b will 'decrement afterwards'. It always does it "before".

Confusion

Look carefully at code and results: Everytime where --- is written without spaces, the result is the same: three. Three is also the result for -- - case. Even with a pure guess, you could say that compiler parses it as -- -. In fact, it actually does it like that, because the C++ Standard requires it to do so. See comments about 'maximum munch' rule. Same follows for other multi-character operators, like ++.

In the other case where you have split that into - --, the compiler had no other option: it had to treat it literally as - -- because of the space in the middle. Just as -- -, this case is obvious and it's perfectly visible which part forms the -- operator and the compiler must obey that.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
  • Yes, indeed. I just tried to explain it in common words. – quetzalcoatl Mar 03 '14 at 12:34
  • `--b` may decrement afterwards. The key point is that `--b` evaluates to the value `(b-1)` . There is no implied ordering of the side-effect. – M.M Aug 09 '14 at 08:40
2

I think this is because of the Maximal Munch Rule. From Wiki:

In computer programming and computer science, "maximal munch" or "longest match" is the principle that when creating some construct, as much of the available input as possible should be consumed.

From Expert C Programming:

The ANSI standard specifies a convention that has come to be known as the maximal munch strategy. Maximal munch says that if there's more than one possibility for the next token, the compiler will prefer to bite off the one involving the longest sequence of characters.

Sadique
  • 22,572
  • 7
  • 65
  • 91
1

That statement is equivalent to 10-6 = 4, rest are equivalent to 9-7 = 3.

#include <iostream>
using namespace std;
int a=10, b=7;
int main() {
    // - and -- opearator               //  Results:  Details after a statement:
    cout << (a--)-b << endl; a=10, b=7;   //    3       Both a and b decremented
    cout << (a --)-b << endl; a=10, b=7;  //    3       Both a and b decremented 
    cout << a- (--b) << endl; a=10, b=7;  //    4       Neither a or b decremented
    cout << (a--) -b << endl; a=10, b=7;  //    3       Both a and b decremented
    cout << (a--)- b << endl; a=10, b=7;  //    3       Both a and b decremented
    return 0;
}
DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
1

In this series of statements

cout << a---b << endl; a=10, b=7;   //    3       Both a and b decremented
cout << a ---b << endl; a=10, b=7;  //    3       Both a and b decremented 
cout << a- --b << endl; a=10, b=7;  //    4       Neither a or b decremented
cout << a-- -b << endl; a=10, b=7;  //    3       Both a and b decremented
cout << a--- b << endl; a=10, b=7;  //    3       Both a and b decremented

you forgot to include one more statement:)

cout << a --- b << endl; a=10, b=7;  //    3       Both a and b decremented

In all these statements

cout << a---b << endl; a=10, b=7;   //    3       Both a and b decremented
cout << a ---b << endl; a=10, b=7;  //    3       Both a and b decremented 
cout << a--- b << endl; a=10, b=7;  //    3       Both a and b decremented
cout << a --- b << endl; a=10, b=7;  //    3       Both a and b decremented

The compiler parses outputed expression as

a-- -b

that is it tries to extract the longest valid token.

The value of the postdecrement operator as for example a-- is the value of its operand before decrementing. So in expression

a-- -b

the value of a-- is 10 and the value of b is 7. The difference is equal to 3.

And you have the only expression with the predecrement operator

cout << a- --b << endl; a=10, b=7;  //    4       Neither a or b decremented

There the value of --b is the value of b after decrementing that is 6. So you have 10 - 6 that is equal to 4.

If you will substitute minus to plus in all these statements you will get the same effect

17
17
18
17
17
17  // this corresponds to my added statement a +++ b

So these operations - -- and + ++ behave in essense the same way.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335