2

I am trying use auto to infer the type.

for (auto i = remaining_group.size() - 1; i >= 0; --i) {
    std::cout << i;
}

I get very large number like 18446744073709534800 which is not expected. When I change auto to int it is the number I expected between 0 and 39.

Is there any reason auto will fail here?

remaining_group's type is a std::vector<lidar_point> and lidar_point is struct like:

struct LidarPoint {
  float x;
  float y;
  float z;
  uint8_t field1;
  double field2;
  uint8_t field3;
  uint16_t field4;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Alex
  • 1,097
  • 3
  • 11
  • 16

3 Answers3

2

When using auto the type of i would be std::vector::size_type, which is an unsigned integer type. That means the condition i >= 0; would be always true, and if overflow happens you'll get some large numbers.

Unsigned integer arithmetic is always performed modulo 2n where n is the number of bits in that particular integer. E.g. for unsigned int, adding one to UINT_MAX gives ​0​, and subtracting one from ​0​ gives UINT_MAX.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
1

Simple reproduction of problem:

#include <iostream>

size_t size()  {return 1;}

int main() {
   for (auto i = size() - 1; i >= 0; --i) {
    std::cout << i << std::endl;
   }
}

size() got type size_t and literal constant 1 would be promoted to size_t, in result auto would become size_t, which cannot be less than zero, resulting in infinite loop and underflow of i.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • Oh, man, integer promotion. I would have expected the final type so be signed, but ... promotion rules. – Vorac May 26 '18 at 12:58
1

If you need a reverse index loop, use operator -->

When you write a normal index loop, you write it with 0, size, and <.

When you write a normal reverse index loop, things become a bit wonky: you need size - 1, >=, 0, and you can't use unsigned index, because unsigned i is always >= 0 so your check i >= 0 always returns true, your loop could run forever.

With fake operator "goes to", you can use 0, size, and > to write the reverse index loop, and it doesn't matter if i is signed or unsigned:

for (auto i = a.size(); i --> 0; ) //or just i--, or i --> 1, i --> 10...
    std::cout << i << ' ';
tnt
  • 1,174
  • 2
  • 10
  • 14