3

I want to print all numbers in [0, 255], but this loop doesn't stop. Why?

for(unsigned char i = 0; i <= 255; i++)
{   
    cout << (int) i << endl;
}
Tavy
  • 861
  • 11
  • 15

7 Answers7

11

i is an unsigned char which typically has a range of [0,255]. In you for loop you are going until i <= 255. When i is 255 you add 1 to it and it wraps back around to 0 which is <= 255 so the loop continues. This is called unsigned integer overflow.

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
3

The range of an unsigned char is [0 to 255] inclusive; telling the for loop to continue if i is less than or equal to 255 causes it to increment i once more, and it wraps from 255 back to 0 (looping forever). You can use a short or int instead to avoid the problem.

Samer
  • 1,923
  • 3
  • 34
  • 54
jrsmolley
  • 399
  • 1
  • 7
3

You're facing an unsigned integer overflow. No matter what you do to an unsigned int, it's always going to be less than or equal to its maximum value (255). You can instead use a larger integer data type for the loop index. If you'd still rather use an unsigned char, a while loop will work:

unsigned char uc = 0;
do {
  // stuff it in here
} while (uc++ < std::numeric_limits<unsigned char>::max());
user2023370
  • 10,488
  • 6
  • 50
  • 83
2

Your loop variable is overflowing.

255 is the max value of unsigned char. i++ then overflows it, and the language standard says it must become 0 again. The loop will never get to 256 which is when the loop condition says it should terminate.

Change i to unsigned int or alternatively, if you really want to save memory, just do:

for(unsigned char i = 0; ; i++) {
    //operations
    if (i == 255)
        break;
}
iPherian
  • 908
  • 15
  • 38
  • That's not saving memory of course. Though +1 but it's the only answer showing how to avoid the cast to char-type – sehe Apr 25 '18 at 07:16
  • @sehe does not the standard say that `int` must be larger than `char`? – iPherian Apr 25 '18 at 07:59
  • That's not relevant. Casting changes the _type_, not just the range: `for (int i = 0; i<=255; ++i) std::cout << i << " ";` doesn't do what `for (int i = 0; i<=255; ++i) std::cout << static_cast(i) << " ";` does! Having the loop-var of the right types avoids the cast. – sehe Apr 25 '18 at 08:03
  • Oh you meant about "saving memory"? In practice it'll be a register, and it's unlikely that the compiler will emit code such that 8 bits of the register can be used for "something else". Compilers try to emit code that _runs_ optimally, not "minimize number of bits strictly depended on" (that might actually make it run slow). – sehe Apr 25 '18 at 08:06
1

Just to add onto the other answers. You're using a char as an integer only here. This is extremely confusing (and misleading) to readers. Stick to datatypes that "make sense" with the data that is being used. Whatever memory you're saving my making it a char instead of an int or short is so infinitesimally small that it will never matter.

If you're interested in types that work well with binary, however, I suggest you look at some documentation for <stdint.h> .

amza
  • 780
  • 2
  • 7
  • 32
1

You loop iterator i is unsigned char, which can hold up to 1 byte or 8 bits. That means the range is 0 to 255(2^8 - 1). And the loop works as desired until i=255 but then in the next iteration it fails when i=255++, i.e. 256 which exceeds the upper limit of the range, it wraps back to 0 [Just google out the datatypes and their ranges, also read about signed/unsigned, unsigned bit etc] so again it starts increment of i up to 255 and so on. Hence it becomes an infinite loop.

To solve the issue just make i capable of holding the number 256, i.e allocate one more bit to it, but we don't have any primitive datatype of size 9 bits so we take the immediate bigger datatype i.e. a short and bingo your loop works absolutely fine.

Hope this clarifies..

paper.plane
  • 1,201
  • 10
  • 17
1

In the 8 bit days this was an important loop, and assembly counters could tackle it. It does not work in a for-loop in C because of the order of evaluations. However, the same kind of trick they used can be reproduced with a do-while.

unsigned char i = 0xFF;
do
    printf("%u ", ++i);
while (i !=255);

Of course this type of code is only suitable for retro or very small embedded systems programming...

This one is plain but straightforward:

unsigned char i;
for (i=0; i<255; i++)
    printf("%u ", i);
printf("%u ", i);
Julek
  • 178
  • 6