-1

Found as a user submission on leetcode for the problem Plus One.

vector<int> plusOne(vector<int>& digits) {
  for (int i=digits.size(); i--; digits[i] = 0)
      if (digits[i]++ < 9)
          return digits;
  digits[0]++;
  digits.push_back(0);
  return digits;
}

Normally there's something in the conditional like i >= 0; How is this for loop terminating and not accesing some -i element?

Podo
  • 709
  • 9
  • 30

1 Answers1

2

A for loop terminates when the second expression is false or when contextually converted to a bool value produces false. In C++, 0 is contextually converted to false; all other integers convert to true in a bool context. (Thanks to M.M.for the link.)

So at the beginning of each loop the expression i-- is evaluated. It's just an expression, so it will produce a result. If the result it produces is zero, the loop will end. If you haven't seen this expression before, here is how it works:

  • It both decrements i and returns the original value of i before it was decremented. So if i were 5, evaluating i-- will have the "result" 5, but as a side effect, i will be 4 after the evaluation.

The big picture: i is decremented by 1 each time, so assuming it starts off positive, it will get down to 0, at which time evaluating i-- will produce 0.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Ray Toal
  • 86,166
  • 18
  • 182
  • 232
  • So a conditional must be included if there is some increment (like `i < 10`; i++`) but when you decrement the conditional is automatically greater than 0? – Podo May 31 '19 at 01:46
  • Any a value other than 0 is true – drescherjm May 31 '19 at 01:47
  • No conditional is needed, interestingly enough. `i--` always returns a value. If `i` were 5, say, then evaluating `i--` will produce the value 5, and _as a side effect_ cause `i` to be 4. – Ray Toal May 31 '19 at 01:47
  • Nice link, I will add that. – Ray Toal May 31 '19 at 01:48
  • Didn't know that was U.B., thanks! Will remove that and look into it, cool. – Ray Toal May 31 '19 at 01:52
  • @M.M. if I am reading [this page](https://en.cppreference.com/w/cpp/language/eval_order) correctly, then starting with C++ 11 you _do_ get guarantees that the value computation of a postfix increment is sequenced before its side-effect. Prior to C++ 11 we had the "sequence points" (remember those?) in which case there may be U.B. – Ray Toal May 31 '19 at 02:04