-4

Why does this code cause an infinite loop:

#include <iostream>
using namespace std;
int main() {
    int y = 5;
    while (y < 6) {
        int y = 7;
        cout << y << endl;
    }
}

yet removing the "int" in the while statement makes it run once normally? (

#include <iostream>
using namespace std;

int main() {
    int y = 5;
    while (y < 6) {
        y = 7;
        cout << y << endl;
    }
}

)

evan holt
  • 25
  • 1
  • 4

2 Answers2

1

In this loop:

while (y < 6) {
    int y = 7;
    cout << y << endl;
}

The inner y is not accessible in the condition test.

If you remove the int in the loop, you're simply assigning a new value to the variable defined outside while, thus terminating it.

Look up Scope on CppReference.

iBug
  • 35,554
  • 7
  • 89
  • 134
0

The behaviour you have observed is called shadowing. This means that a variable is "shadowed" by another variable in an inner scope. (iBug has already provided a link to the C++ scope rules) The outer scope (in your case while(y < 6)) can not access the inner scope (in your case int y = 7;) and vice versa. Both have the same name, but they are completely separate variables in separate scopes.

This is a very common source for errors (you also find a lot of them here) and doesn't only happen with loops and other scope brackets, but also very often with class members. Imagine a class:

class MyClass {
    int a;
public:
    void getA( int a ) { return a; }
};

getA() defines a parameter a, which shadows the class member a. This is at least bad style, but even more probable a source of errors. We don't know - did you want to return the member a or did you really mean the parameter? So this should be avoided.

Here's a real life example on Stackoverflow - see my comment below the question (regarding the 3rd constructor)

Possibilities to avoid these kind of errors are:

  • Use highest possible compiler warnings and perhaps even warnings as errors. Compilers can warn about those kind of shadowing issues.
  • Use a name scheme. A common scheme is members with a m, m_ prefix, a _ suffix and the like. If the member name in the MyClass would have been m_a, this would have reduced confusion. Of course this doesn't help in your example, but it's a good idea nevertheless.
user2328447
  • 1,807
  • 1
  • 21
  • 27