6

I'd like a loop that uses a UInt16 (ushort) to loop through all of its values. However, this doesn't do it:

for( ushort i = 0; i < UInt16.MaxValue; i++ )
{
    // do something
}

The problem is that the loop will quit when i == 0xFFFF and not "do something". If I change the 'for' statement to "for(ushort i = 0; i <= UInt16.MaxValue; i++ )", then it becomes an infinite loop because i never gets to 0x10000 because ushorts only go to 0xFFFF.

I could make 'i' an int and cast it or assign it to a ushort variable in the loop.

Any suggestions?

Robert Deml
  • 12,390
  • 20
  • 65
  • 92

5 Answers5

17

Use a do...while loop

ushort i = 0;
do
{
    // do something
} while(i++ < UInt16.MaxValue);

There is an interesting discussion of testing loops at the top vs. the bottom here.

Community
  • 1
  • 1
Chris Marasti-Georg
  • 34,091
  • 15
  • 92
  • 137
  • Much nicer than my answer. :) – Jeff Yates Oct 23 '08 at 19:31
  • That's brilliant, yet disturbing somehow ;-) – Ferruccio Oct 23 '08 at 19:34
  • extremely disturbing; i'm about to remove my answwer as I made a goof, but counting down would work too, yes? like for(ushort i=UInt16.MaxValue; i>=0; i--) – warren Oct 23 '08 at 19:39
  • Nope, sorry warren. Since i is unsigned, it would never be less than 0. You'd still want a do...while. – Chris Marasti-Georg Oct 23 '08 at 19:48
  • That's why I didn't say "less than" i picked "greater than or equal" – warren Oct 23 '08 at 19:49
  • though you may still be right - I haven't actually tried it, and my brain's about fried on logic and counting right now :P – warren Oct 23 '08 at 19:50
  • warren - if i can't be negative, it will always be greater-than-or-equal-to 0. – Chris Marasti-Georg Oct 23 '08 at 19:55
  • Oddly enough, most of the arithmetic and comparison for ushort is being done with 4 byte ints (take the above code and compile it and load it up in ildasm or reflector)! Personally, I'd be inclined to use an int as the loop variable for this particular case. – plinth Oct 23 '08 at 19:57
  • Normally I would use an int, but there are calls where I need 'i' to be a ushort to call the correct method (overloading). I'd rather not have to create another variable just for the cast to ushort. – Robert Deml Oct 23 '08 at 20:09
  • You don't have to create another variable, just cast it explicitly to ushort. – Ferruccio Oct 23 '08 at 20:26
  • It could be a ushort and not be computed with 4-byte ints if it were not a PC architecture. I used to work on an embedded cpu where this question came up every day. – Mnebuerquo Oct 23 '08 at 20:34
5

UInt16.MaxValue evaluates to 0xffff, not 0x10000. I think you can do this with a do/while loop, as a variation on burkhard1979's answer.

ushort i = 0;
do {
   ...
} while (++i != 0);
spoulson
  • 21,335
  • 15
  • 77
  • 102
4

You could simply replace the for by a do-while loop.

ushort i = 0;
do
{
i++;
...
} while(i!=UInt16.MaxValue);
Burkhard
  • 14,596
  • 22
  • 87
  • 108
1

does it have to be a short? why not just

for(int i = 0;i<=0xFFFF;i++)
{
  //do whatever
}
Kevin
  • 7,162
  • 11
  • 46
  • 70
1

Assuming that your code suffers from an off by one error (the current code, stops just before having the final value evaluated. Then the following might answer you.

Very simple, as your counter is a 16 bit unsigned integer, it can not have values bigger than 0xffff, as that value is still valid, you need to have some value that extends beyond that as the guard. However adding 1 to 0xffff in 16 bits just wraps around to 0. As suggested, either use a do while loop (that does not need a guard value), or use a larger value to contain your counter.

ps. Using 16 bit variables on modern machines is actually less efficient than using 32 bit variables as no overflow code needs to be generated.

Paul de Vrieze
  • 4,888
  • 1
  • 24
  • 29