-1

Still learning C++, I'm wonder why when comparing two operands, such as in this if-statement:

if (array[currentIndex] > array[currentIndex + 1])
            std::swap(array[currentIndex], array[currentIndex + 1]);

the less-than evaluation doesn’t work when written this way with an increment operator (prefix or postfix):

if (array[currentIndex] > array[++currentIndex])
            std::swap(array[currentIndex], array[++currentIndex]);

or when using an increment/decrement operator in a for-loop condition:

for (int currentIndex = 0; currentIndex < --length; ++currentIndex)

Any explanation would great, thank you.

  • 5
    The order of evaluation of `currentIndex` and `++currentIndex` in your second example is unspecified, so you could get two identical values, or not. But the `for` loop looks fine to me, so what is wrong with it? – Quentin May 24 '17 at 00:09
  • 5
    `++var` is not identical to `var + 1`. – Mooing Duck May 24 '17 at 00:10
  • 1
    As Documentation surely must be useful for something, here is [some blurb about the increment operator](https://stackoverflow.com/documentation/c/256/operators/942/increment-decrement#t=201705240013444922048). – Ken Y-N May 24 '17 at 00:15
  • @Quentin Can you explain at little about why the order of evaluation is unspecified in this case? Thank you much. – Cory Greenhalgh May 24 '17 at 00:25
  • @KenY-N thank you for your help here – Cory Greenhalgh May 24 '17 at 00:35
  • 2
    @Quentin it's undefined behaviour prior to C++17 (your comment leaves room for reader to think it is unspecified behaviour) – M.M May 24 '17 at 00:52
  • @M.M I actually thought it was merely unspecified. Looked at the [doc](http://en.cppreference.com/w/cpp/language/eval_order#Undefined_behavior_2), fixed my knowledge. Thanks for the heads-up. – Quentin May 24 '17 at 00:55

2 Answers2

2

You cannot blindly substitute one expression with another. Why? Let's look into simpler example:

tmp = currentIndex + 1;

vs

tmp = ++currentIndex;

what is the difference? You will get the same value in tmp as a result but first expression would not change variable currentIndex while second one would. So for example you can execute first exression many times with the same result, while second one will give you different result every time.

On another side you need to be careful with changing variable and using it within the same exression - you can easily get Undefined Behavior, as compiler allowed to optimize exressions different way and you do not know when exactly variable would be changed. Detail can be found here

As for this loop:

for (int currentIndex = 0; currentIndex < --length; ++currentIndex)

if it is used in the same loop this seem to be the same mistake as before length - 1 replaced with --length, the problem is that condition checked every iteration so each time length would be decreased. But length - 1 simply means you want to iterate once less than size of array, which makes sense as you access array with currentIndex + 1 and do not want to access invalid index. This is pure speculation or educated guess, but without context it is difficult to say for sure.

Slava
  • 43,454
  • 1
  • 47
  • 90
  • this was a very good explanation, thank you. I believe I was mistakenly assuming that use of `++var` gave the same result as the expression `var + 1`. I also didn't realize the expression used in an if-statement is treated as any other expression statement i.e. any side-effects of assignment/use of operators affect the mentioned variables, rather than simply for a comparison condition during the if-statement. – Cory Greenhalgh May 24 '17 at 00:55
0

The order of evaluation of the operands of the operator > in the condition of the if statement

if (array[currentIndex] > array[++currentIndex])
            std::swap(array[currentIndex], array[++currentIndex]);

and the order of evaluation function arguments is not specified. So this statement yields undefined behavior.

Moreover if to assume that the order of the evaluations is specified and is from left to right nevertheless the variable currentIndex is increased twice in this case. So the substatement of the if statement will deal with different elements of the array.

As for the loop statement

for (int currentIndex = 0; currentIndex < --length; ++currentIndex)

then there is nothing unusual. ++currentIndex evaluates after the body of the loop statement while the condition currentIndex < --length is evaluated before the body of the loop.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 4
    Even if there was a defined order, that first code would be wrong. OP seems to think `++var` is identical to `var + 1` – Mooing Duck May 24 '17 at 00:11
  • @MooingDuck Your comment does not make sense because the OP thinks that the order of evaluation is defined from left to right. – Vlad from Moscow May 24 '17 at 00:14
  • 1
    @Vlad, even if it evaluated left-to-right, you'd be comparing, say elements `[0]` and `[1]`, but then swapping `[1]` and `[2]`. And `currentIndex < --length` will decrease `length` every time round which although well-defined, is most likely not what the OP wants. – Ken Y-N May 24 '17 at 00:18
  • @KenY-N He just wrote an example of two possibilities in one statement without thinking about the result. That is its question is about why he can not substitute one operand with the expression I + 1 for the expression ++i. – Vlad from Moscow May 24 '17 at 00:20
  • @KenY-N Moreover he explicitly mentioned that "the less-than evaluation doesn’t work" – Vlad from Moscow May 24 '17 at 00:22
  • 1
    I appreciate the input @mooingduck and @vlad - can you explain why `++var` and `var + 1` are not identical? Also, can you explain why that particular statement yields undefined behavior? Very thankful for your help – Cory Greenhalgh May 24 '17 at 00:22
  • @CoryGreenhalgh The problem is that if the order is not specified then the expressions can be evaluated either from left to right or from right to left depending on the used compiler. If for example the expressions are evaluated from right to left then the both indices of the condition will be equal each other. – Vlad from Moscow May 24 '17 at 00:24
  • 1
    @CoryGreenhalgh The difference between `++var` and `var + 1` is `++var` will increment the value stored in var and return the result where as `var + 1` will just return the sum of `var` and `1`. – C.Liddell May 24 '17 at 00:27
  • @C.Liddell I think that it is clear without your comment. – Vlad from Moscow May 24 '17 at 00:28
  • 1
    @VladfromMoscow OP asked "Can you explain why ++var and var + 1 are not identical?" just 3 comments back. – C.Liddell May 24 '17 at 00:29
  • @C.Liddell Thank you for the input - so by using `++var` in the if-statement condition in my code, I'm actually incrementing the stored value of that variable at that point? I thought it would simply be a comparison when the statement is read, I didn't realize it would change the variable itself in that conditional expression. – Cory Greenhalgh May 24 '17 at 00:29
  • 1
    @CoryGreenhalgh yes. `if` evaluates the result of any expression, and it does not inhibit its side-effects. – Quentin May 24 '17 at 00:30
  • 1
    @CoryGreenhalgh Exactly, by using `++var` your changing the value stored in `var` to `var+1`, so if `var` is referenced again after this statement is executed, it's actually referring to the incremented value. – C.Liddell May 24 '17 at 00:32
  • @C.Liddell You do not understand his question. He asked about the condition if (array[currentIndex] > array[++currentIndex]). If to assume that the expressions are evaluated from left to right then its result (true or false) should be the same as for the condition if (array[currentIndex] > array[currentIndex+1]) However the order of evaluation of the expressions are not specified. – Vlad from Moscow May 24 '17 at 00:32
  • @Quentin Wow, ok that really clears things up. Thank you! – Cory Greenhalgh May 24 '17 at 00:32
  • 2
    @VladfromMoscow Actually I think you and c.liddell answered my question in two different but helpful ways. I'll look more into the unspecified order of evaluation, and now I know that `++var` will change the variable itself when used in an expression. That makes other answers more clear as well, specifically the `++var` != `var + 1` comment. – Cory Greenhalgh May 24 '17 at 00:34