-8

How many times will this loop execute?

unsigned char half_limit = 150;

for (unsigned char i = 0; i < 2 * half_limit; ++i)
 {
  // do something;
 }
Community
  • 1
  • 1

2 Answers2

4

Transforming the comments into appropriate answer:

2*half_limit results in 300 due to integer promotion (link is for C, but same rules apply for C++), however, this value cannot be stored in unsigned char (i!!!), which means that the loop variable never can reach it; instead, it will overflow when being 255 at ++i and thus "restarts" with 0.

The result is an infinite loop (assuming the do something part does not modify half_limit).

Side note 1: This applies for most common and ancient hardware, as these typically have eight bit wide char types. However, C++ standard's only (and just the same in C...) requirement for unsigned char is being able to minimally hold the values from 0 to 255 (and actually, not having larger size than unsigned short). Signed and unsigned char being larger than 8 bit is absolutely valid, and such hardware even exists (e. g. some DSP from TI with 16-bit char). On such hardware, the loop would have run 300 times!

Side note 2: If there are no visible side effects in the do something part, the compiler is allowed to optimise the loop away entirely, so it might not be run at all; however, we have undefined behaviour in the endless loop case (refer to Jarod'sanswer)!

Conclustion: As long as we do not know the hardware we are running on, what the do something part really contains and which compiler was used with which optimisation flags, we actually cannot tell anything at all...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • The *minimum requirement* of the standard is that `unsigned char` represent the range `0` to `255`. That is common in practice, but an implementation is permitted to provide an `unsigned char` with a larger range. – Peter Mar 28 '18 at 10:53
  • @Peter Sure, already worked on architectures with CHAR_BIT == 16... But if it were the case in given situation, we would not have ended up in endless loop (not even with CHAR_BIT == 9)... – Aconcagua Mar 28 '18 at 11:33
  • The loop does not loop because the optimizer removes the whole loop because it does nothing. – user743414 Mar 28 '18 at 11:54
  • 2
    @user743414 Actually, if the `do something` really just is a comment, we have undefined behaviour, so *anything* could happen... Just removing the loop only is the most likely outcome. Actually, the compiler is not forced to optimise the loop away either - consider -O0 flags (GCC/clang)... – Aconcagua Mar 28 '18 at 11:56
0

in i < 2 * half_limit, we have integer promotion: we compare so i with 300.

i, as unsigned char would never reach that limit.

Overflow of unsigned char is well defined, and wrap around maximum value.

So the loop in infinite.

So unless // do something; does any of:

  • makes calls to library I/O functions
  • does access or modify volatile objects
  • or performs synchronization operations or atomic operations

the code would be Undefined Behavior (UB)

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • @Peter: See for example [is-infinite-loop-still-undefined-behavior-in-c-if](https://stackoverflow.com/questions/41320725/is-infinite-loop-still-undefined-behavior-in-c-if-it-calls-shared-library) – Jarod42 Mar 28 '18 at 11:00
  • 1
    `// do something;` can also modify `half_limit`. – Daniel Langr Mar 28 '18 at 11:48
  • @DanielLangr: Indeed, we all assume that `half_limit` wasn't modified. Else with with `half_limit = 0;`, there is only one iteration :-) – Jarod42 Mar 28 '18 at 11:56