-1

Code Snippet 1:

int i=1;
for(;;){
    if (i<5){
        cout<<"Hello World"<<endl;
        i++;
    }
}

Code Snippet 2:

int i=1;
for(;;){
    if (i<5){
        cout<<"Hello World"<<endl;
    }
    i++;
}

Snippet 1 produces an output where "Hello World" is printed 4 times and then the loop continues with no output, which was expected. But, "Hello World" is printed indefinitely in snippet 2. Why does the condition (i<5) not checked in snippet 2 even after i=>5? How does incrementing i (i++) inside or outside the if-block in these snippets making such a difference?

  • 3
    What will happen when `i` reaches its maximum value, and you increment it again? – Jerry Coffin Aug 31 '23 at 07:07
  • 2
    In the second, `i` will overflow, and that makes the program undefined. (Print the value of `i` as well.) – molbdnilo Aug 31 '23 at 07:07
  • @molbdnilo I checked printing i too. It prints indefinitely. Can you please explain more about the overflow and program undefinition. – Utkarsh Kumar Aug 31 '23 at 07:29
  • 1
    Read about undefined behaviour in a [good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282). – molbdnilo Aug 31 '23 at 07:31
  • 1
    The code has [undefined behaviour](https://en.cppreference.com/w/cpp/language/ub). Anything could happen. – Jesper Juhl Aug 31 '23 at 07:47
  • @molbdnilo: both snippet has UB, infinite loop without "side effects" is UB too. – Jarod42 Aug 31 '23 at 07:52
  • @JesperJuhl Are you sure? That's only true for infinite loops without side effects right? Snippet 2 seems to be a kind of a gray area case to me, there are initial side effects. Followed by a time there is no side effect... followed by integer overflow (making it all happen again). So even though this is bad code I do not actually think UB is involved. – Pepijn Kramer Aug 31 '23 at 08:51
  • @PepijnKramer signed integer overflow is UB and there's no forward progress in either loop, also UB. – Jesper Juhl Aug 31 '23 at 09:48

1 Answers1

1

In the first snippet, when i reaches the value 5, it is no longer changed and keeps that value.

In the second one, i keeps being increased. It will overflow, and that is enough to invoke Undefined Behaviour. Common implementations use 2-complement for negative numbers, so INT_MAX + 1 gives... a negative number (INT_MIN). Which is indeed smaller than 5!

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 5
    Additionally, due to the forward-progress guarantee, both loops are UB anyway. – You Aug 31 '23 at 07:35
  • @You but these loops do I/Os, so produce observable behaviours, isn't it? – Jean-Baptiste Yunès Aug 31 '23 at 09:21
  • @Jean-BaptisteYunès Yes, but once they've done so they stop "making progress" as defined by the standard. Informally you could argue that both programs are semantically equivalent to a finite loop with I/O output, followed by an infinite loop with no I/O; the latter loop violates the forward progress guarantee. – You Aug 31 '23 at 11:18
  • @you I understand that but the requirement is that the **compiler** is able to make such elimination, hard to believe this is inferred by compilers (even in this case that is almost trivial). – Jean-Baptiste Yunès Aug 31 '23 at 14:22
  • @Jean-BaptisteYunès What compilers might infer isn't really relevant; the loop stops making forward progress and therefore it is UB. In this particular case, with `i<5`, things happen to "work" (infinite loop is not optimized out), but with `i<2` suddenly the loop is entirely eliminated: https://godbolt.org/z/KaG63E7c7 – You Sep 01 '23 at 08:16