2

I'm not quite sure why visual studio is giving me the error message "Ill-defined for-loop: 'unsigned int' values are always of range '0' to '4294967295'. Loop executes infinitely" for the following code:

for (unsigned int i = list->GetCount() - 1; i >= 0; i--)
{
    // do stuff to each item (specifically in reverse order)
}

Could someone please explain to me?

Edit: GetCount() returns an unsigned int, and I do not have control over this

Gary Allen
  • 1,218
  • 1
  • 13
  • 28
  • 5
    Being an `unsigned` type, `i >= 0` is always true, by definition. A variable of `unsigned` type can't possibly be negative. – Igor Tandetnik Jun 28 '20 at 15:48
  • Oh! I was forgetting about the fact that i-- will simply "wrap" back around when i gets to 0. What would be the best way to traverse the list in negative order then? My "get count" function returns an unsigned int – Gary Allen Jun 28 '20 at 15:50
  • You could cast the getCount() function to an int and then set i to an int. This would prevent any "wrapping around" when i becomes a negative number. – Telescope Jun 28 '20 at 15:51
  • 1
    `unsigned` is overrated. – molbdnilo Jun 28 '20 at 15:56

3 Answers3

5

When you subtract 0 from an unsigned type, you don't get a negative number, but a very large positive number.

That means this condition:

i >= 0

will always be true, resulting in an infinite loop.

You can fix this by doing:

for (int i = static_cast<int>(list->GetCount()) - 1; i >= 0; i--)

Note that the cast needs to be done before the subtraction by 1, otherwise you will have the same wrapping issue when GetCount returns 0.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • That makes total sense, can't believe I missed that. How do I go through all items in the list then if my GetCount() function returns an unsigned int? Will a simple c-style cast to an int work? – Gary Allen Jun 28 '20 at 15:52
  • No, don't do a c-style cast. A static_cast is sufficient. Added to the answer. – cigien Jun 28 '20 at 15:53
  • 1
    Thanks. What's wrong with a c-style cast in this situation? – Gary Allen Jun 28 '20 at 15:55
  • 1
    This solution won't work if `GetCount()` returns a value larger than the maximum of a signed integer. You'd need to either cast to a larger type or use a different solution – UnholySheep Jun 28 '20 at 15:55
  • In *this* situation it's fine. But it's bad practice in general. `static_cast` is safer and should be used when sufficient. – cigien Jun 28 '20 at 15:55
  • @UnholySheep that's true as well, what data type should I use then? Or is there a better solution? – Gary Allen Jun 28 '20 at 15:57
  • I suggest returning an `int` from `GetCount` directly. Added to the answer. – cigien Jun 28 '20 at 15:58
  • @cigien I don't have control over what GetCount returns – Gary Allen Jun 28 '20 at 15:59
  • @GaryAllen using iterators would be the best solution and this question has a possible solution for using indices as well: https://stackoverflow.com/questions/3610933/iterating-c-vector-from-the-end-to-the-begin – UnholySheep Jun 28 '20 at 15:59
  • @UnholySheep my list is actually a listBox from a GUI library - no iterators and no control over what GetCount returns – Gary Allen Jun 28 '20 at 16:01
  • @GaryAllen you do not have control over what GetCount returns, but you have control on creating a helper function which will call GetCount, convert the result into signed variable and return it that way. You solve your problem that way once and then you will never have to worry about that again. – Lajos Arpad Jun 28 '20 at 20:13
  • You can also invert the for cycle to start from 0 and get to one below the result of that function. – Lajos Arpad Jun 28 '20 at 20:14
1

You're making a common error here. When you declare i as an unsigned int, you are guaranteeing that it will never be negative; instead, it will "wrap around" to an extremely high number whenever it goes below 0.

What this means is that your for-loop will never terminate! Your terminating condition, i >= 0, will never be satisfied as the unsigned integer will count down 2, 1, 0, 4294967295, 4294967294... and so on forever.

To fix this, change the unsigned int type to an int type.

Telescope
  • 2,068
  • 1
  • 5
  • 22
0

The execution of you're loop will never end.

There are a couple solutions, I like the first two. The thirth will cause list->GetCount() to be called n times.

for (unsigned int i = list->GetCount() - 1; i != UINT_MAX; --i);
for (unsigned int i = list->GetCount() - 1; i != (unsigned int)-1; --i);
for (unsigned int i = list->GetCount() - 1; i <= list->GetCount() - 1; --i);

You could also convert to a int, but you must know for sure that list->GetCount() will be less or qual to INT_MAX.

Alex de Kruijff
  • 235
  • 2
  • 5