Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing variables in an enclosing scope(not global) hidden by local declaration in C++?

Tags:

c++

The scope resolution operator :: can be used to access a global variable shadowed by a local declaration. How do you achieve the same for a variable declared in an enclosing scope but not global?

int main() {
  int i = 10;

  if (1) {
    int i = 5;
    std::cout << "Local i: " << i << std::endl;

    std::cout << "Main's i: " << ?? << std::endl; //How to access main's i?
  }

  return 0;
}

I know this is bad practice. But I was just curious to know if this was possible. I reckon it's not.

An explanation of why it's not possible or how it is would be useful.

like image 984
iambk Avatar asked Jun 27 '19 03:06

iambk


People also ask

Can a global variable be hidden by a local variable?

This rule finds declarations of local variables or parameters that hide a global variable. Such declarations create variables with the same name but different scopes. This makes it difficult to know which variable is actually used in an expression.

What is the scope of local declaration?

In Java, the scope of a local variable is the body of the method in which it is declared. In other words, the variable is visible in the body of the method where its declaration appears, but it is not visible on the outside the method.

What is the scope of local variable in C?

In simple terms, scope of a variable is its lifetime in the program. This means that the scope of a variable is the block of code in the entire program where the variable is declared, used, and can be modified.

How can you access a global variable inside the function if function has a variable with same name?

To access a global variable in a function, if the function has a local variable with the same name, we use the global keyword before the variable name.


1 Answers

This is unfortunately not possible. Compiler warning options, like -Wshadow for GCC, can help avoiding such situations:

-Wshadow

Warn whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C) or whenever a built-in function is shadowed. Note that in C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows a struct/class/enum. Same as -Wshadow=global.

In your example, for instance, you'd get a warning like:

: In function 'int main()':

:7:9: error: declaration of 'i' shadows a previous local [-Werror=shadow]

7 |     int i = 5;

  |

As @L. F. points out in a comment below, you can use references to still have access to the other i:

#include <iostream>

int main() {
  int i = 10;
  if (1) {
    int& nonlocal_i = i; // just before shadowing
    int i = 5;
    std::cout << "Local i: " << i << std::endl;
    std::cout << "Main's i: " << nonlocal_i  << std::endl;
  }
  return 0;
}

But -Wshadow will still complain, and if you were going the extra mile to find an alternative name, you could just name the local i differently.


Note: As user4581301 points out in a comment, code like int& i = i; doesn't do what you'd expect in an inner scope:

#include <iostream>

int main()
{
    int i = 4;
    {
        int& i = i;
        std::cout << i;
    }
}

It tries to use the variable i to initialize itself. In Microsoft's compiler you get a compilation error like:

error C4700: uninitialized local variable 'i' used

In GCC, if you turn all the warnings on, you get this message:

error: reference 'i' is initialized with itself [-Werror=init-self]

But it silently compiles and does the wrong thing if you don't have the warnings turned on

like image 60
Ayxan Haqverdili Avatar answered Oct 19 '22 12:10

Ayxan Haqverdili