-1

I tried this on Mac OS and Redhat (g++ 6.3.1), file "test.cpp": g++ -Wall -Wextra -Wconversion -pedantic -o test test.cpp

#include <iostream>
int main()
{
    int a = 777;
    for (int k = 0; k < 2; ++k) {
        a = 111;      // external a
        int a = 0;    // internal a 
        for (int j = 0; j < 3; ++j) a += j + k;
        std::cout << "internal a: " << a << std::endl;
    }
    std::cout << "external a: " << a << std::endl;
}

Output: internal a: 3 internal a: 6 external a: 111

The question why does it compile? I always thought (20+ years) that scoping rules in C++ are very strict (for good). Apparently two similarly named variables "a" exist in the same scope. The example came from the real code where I made a mistake.

Albert65
  • 39
  • 3
  • Good question. I never think about this. I personally think cannot use `a` before it is declared in local scope (if any) is better. – apple apple Oct 02 '18 at 14:12
  • I think that is not a good duplicate. I'd guess this question ask for **why** this is allowed. and is a good question IMHO (although may be closed as opinion based) – apple apple Oct 02 '18 at 14:24
  • Turn your compiler warning level up. `-Wall -Wextra -Wshadow` this will tell you about all the doggy situations in your code. Then add `Werror` to make sure you treat warnings like the logical errors that they are. – Martin York Oct 02 '18 at 14:30
  • @appleapple The question is "why?". But the reason for the question is that the OP thinks that `a` appears 2 times in the same scope. Since it does not, the question why, is no longer really the right question. If the OP wants to ask why can `a` appear in different scopes then it would be more valid but almost definitely answered somewhere. I think this is an appropriate duplicate. – Fantastic Mr Fox Oct 02 '18 at 14:35
  • if this was not allowed many macros would break (which would not necessarily be a bad thing ;). Consider `#define foo { int a = 1; std::cout << a; }` and then used in a scope that already declared an `a`. Maybe not the best example, but I hope you get the idea – 463035818_is_not_an_ai Oct 02 '18 at 15:01
  • @user463035818 your macro introduce new scope so it should keep working. – apple apple Oct 03 '18 at 01:38
  • @FantasticMrFox IMHO the inner block should reject `a`'s use before it is declared, I'm pretty surprise this is not the case (especially no warning -other than shadow- is given for this case). The dupe Q does not mention similar problem. And the A does not clarify on this. – apple apple Oct 03 '18 at 01:43

1 Answers1

2

They are not in the same scope. This is called variable shadowing and is legal (but usually warned against by compilers with -WShadow).

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
  • Thanks everybody for replies. The right question, as mentioned above, would be "why this is allowed at all?". Potentially this can lead to very tricky bugs without obvious benefits of having variable shadowing enabled. Although the question is not unique as such, it clearly manifests the potential pitfall. For now on, I shall be always using -Wshadow along with -pedantic, etc. Thanks for pointing out. – Albert65 Oct 02 '18 at 15:06
  • The problem is more subtle than I expect. Let me reiterate. If I commented the second assignment (a = 111), with -Wshadow I still get a warning: #include int main() { int a = 777; for (int k = 0; k < 2; ++k) { // a = 111; int a = 0; for (int j = 0; j < 3; ++j) a += j + k; std::cout << "internal a: " << a << std::endl; } std::cout << "external a: " << a << std::endl; } – Albert65 Oct 02 '18 at 15:24
  • @Albert65 Yes, because you still have a shadowing instance. Its not the assignment that makes it shadowing, it is the fact that you have 2 objects with the same name in different scopes. comment out the second `int a` and the warning goes. But be aware that the behaviour of the program changes. – Fantastic Mr Fox Oct 02 '18 at 15:31
  • It is good to recall that the scoping rules rely on the order of variable declarations rather than block {..} borders, and avoid duplicate names whenever possible. – Albert65 Oct 02 '18 at 15:50