The elegant way is to just use an int.
CPUs don't have 8bit registers, or don't want to operate on 8bit values these days, which means that when you write this:
uint8_t j = 0; do {...} while (++j);
You're actually asking the compiler to transform it into something like this abomination:
int j = 0; do {...} while( (j=(j+1)&0xFF) != 0 );
...and then also asking the compiler to try and optimize such horrible code for you!
After wasting a bunch of time optimizing your code, it will be the same as if you'd just written what DekuTree posted, which is a perfectly idiomatic loop without any clever obfuscation applied:
for( int i=0; i!=256; ++i ) {...}
If there is a more optimal way of looping on a specific platform, a clever compiler will be able to transform any of the above loops to it, seeing they're all exactly equivalent in behavior!