10

So I was just trying to fill a buffer with consecutive numbers 0-255. I didn't think much on it and ended up in an infinite loop.

uint8_t i;
uint8_t txbuf[256];

for (i=0; i<256; i++) {
    txbuf[i] = i;
}

the problem being that i will never be 256 as it rolls over to zero after 255.

my question is, is there a way to do this loop without bumping i up to a 16 bit value?

Note: I know I could change the loop to i<255 and add another line for the final spot but I'm trying to figure out of there is a nicer looking way.

timrau
  • 22,578
  • 4
  • 51
  • 64
user3817250
  • 1,003
  • 4
  • 14
  • 27
  • 3
    Don't use an 8-bit `i`. Since a `uint8_t` can only have the values 0...255, `i < 256` will always be true. Use a regular `int` for the loop counter and just drop the extra bits on assignment. – Lee Daniel Crocker Dec 05 '14 at 17:30
  • the accepted answer works with an 8-bit value. – user3817250 Dec 05 '14 at 17:33
  • If you want to be able to end the loop after 0 iterations, you can't end it after 256, and vice versa. 0 to 256 = 257. – potrzebie Dec 05 '14 at 17:35
  • 1
    True, but a bad habit, I think. Loop indices should generally always be plain `int` unless there's some compelling reason they can't. On an ARM, for example, the accepted code would have to do a lot of extra masking since it can only do 32-bit fetches and stores. – Lee Daniel Crocker Dec 05 '14 at 17:38
  • `int` must have at least 16 bits, so there's no reason to use `uint8_t` in this case. In most cases using native width variables will generally be faster than 8-bit ones (except in arrays) https://stackoverflow.com/q/163254/995714 https://stackoverflow.com/q/5069489/995714 https://softwareengineering.stackexchange.com/q/144792/98103 And even in the 8-bit world a smart compiler will optimize the loop `for (int i = 0; i < 256; i++)` out without any use of 16-bit math, like how the 32-bit compiler [iterates over all unsigned integers](https://stackoverflow.com/q/40432995/995714) – phuclv Apr 07 '18 at 13:42

6 Answers6

14
uint8_t txbuf[256];
uint8_t i = 0;

do {
   txbuf[i] = i;  
} while (i++ != 255);

or

uint8_t txbuf[256];
uint8_t i = 255; 

do {
   txbuf[i] = i;  
} while (i--);
zavg
  • 10,351
  • 4
  • 44
  • 67
5

Use a do ... while loop so that you perform the action before checking the condition:

uint8_t i = 0;
uint8_t txbuf[256];

do {
    txtbuf[i] = i;
} while(i++ < 255);
Squirrel
  • 2,262
  • 2
  • 18
  • 29
  • I think it would be good to note that at the end of this loop `i==0` however that would only really matter if there is a `break` in the loop and you wanted to keep track of the index at the break point. – user3817250 Dec 05 '14 at 17:40
3

The do..while loops in the other answers are probably what you want, but if you specifically want to use a for loop you can add a break statement:

uint8_t i;
uint8_t txbuf[256];

int main(void)
{

    for (i=0; ; i++) {
        txbuf[i] = i;
        if (i == 255) break;
    }

}
Scooter
  • 6,802
  • 8
  • 41
  • 64
2

uint8_t ranges from 0-255 so it never becomes 256. Since we see that your array is also of type uint8_t the value it can store is also from 0-255 so what makes you loop for values greater than 255?

Just keep your check as i<255 and when you exit the loop you know the value of i is 255,use it accordingly.

Else use do while as suggested by others.

Gopi
  • 19,784
  • 4
  • 24
  • 36
1

The following gcc (5.0) has a feature to check if an overflow occured.

uint8_t i = 0;
uint8_t txbuf[256];

do
{
    txbuf[i] = i;
}while(!__builtin_add_overflow(i,1,i));

More details at https://gcc.gnu.org/gcc-5/changes.html

Rudi
  • 19,366
  • 3
  • 55
  • 77
0

Consider this:

uint8_t txbuf[256];
uint8_t i = 0;

do {
    txtbuf[i] = i;
} while(++i != 0);

The code allows for a change in type.