tags:

views:

1214

answers:

5

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?

+16  A: 

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.

Chris Marasti-Georg
That's the ticket!
rpj
Much nicer than my answer. :)
Jeff Yates
That's brilliant, yet disturbing somehow ;-)
Ferruccio
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
Nope, sorry warren. Since i is unsigned, it would never be less than 0. You'd still want a do...while.
Chris Marasti-Georg
That's why I didn't say "less than" i picked "greater than or equal"
warren
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
warren - if i can't be negative, it will always be greater-than-or-equal-to 0.
Chris Marasti-Georg
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
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
You don't have to create another variable, just cast it explicitly to ushort.
Ferruccio
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
+4  A: 

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

ushort i = 0;
do
{
i++;
...
} while(i!=UInt16.MaxValue);
Burkhard
+5  A: 

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
I prefer this answer. Much more fun!
Paul Hargreaves
The != 0 is redundant. But this method is the sort of thing I use. Integer overflow ftw!
Artelius
True. I'm a little used to C#, which doesn't implicitly convert int to bool like C/C++ does.
spoulson
Since it is tagged C# I think it would not work without the !=0
Burkhard
+1  A: 

does it have to be a short? why not just

for(int i = 0;i<=0xFFFF;i++)
{
  //do whatever
}
Kevin
+1  A: 

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