2

I'm a bit confused by global constants. My (beginner level) understanding is that 'global' variables are defined outside of a block and have program scope (source: http://www.learncpp.com/cpp-tutorial/42-global-variables/). But the program:

#include <iostream>

const double x=1.5;

int main(){
        std::cout << "1) x=" << x << std::endl;
        double x=2.5;
        std::cout << "2) x=" << x << std::endl;
        //const double x=3.5;
        return 0;
}

compiles in g++ (GCC, latest 64-bit version) without any problems, even with -Wall.

The output:

1) x=1.5
2) x=2.5

This is confusing to me. The fact that the first cout evaluates means that main recognises 'x' as a 'global' variable (it wasn't defined in main's scope). If that is the case, why does it let me redefine 'x'?

Then, if you uncomment the commented third declaration, g++ throws up a redeclaration error. Meaning, my first declaration can't have been 'global', in the sense I defined :S

edit: okay, question has nothing to do with global variables, but scopes: e.g same problem in http://pastebin.com/raw.php?i=V5xni19M

badger5000
  • 650
  • 7
  • 17
  • 2
    You're shadowing the global variable with a local one. `double x` declares a new local `double`, hiding the global one. You're not "redefining" it. – Simple Oct 11 '13 at 14:16
  • 1
    Further reading: http://stackoverflow.com/questions/4269034/what-is-the-meaning-of-prepended-double-colon-to-class-name – Moo-Juice Oct 11 '13 at 14:26

6 Answers6

8
#include <iostream>

const double x=1.5;

At this point in code, there is one object named x in the global scope, and it is of type const double.

int main(){
        std::cout << "1) x=" << x << std::endl;

At this point, there's still just one x visible (the global one), so that's what the name x refers to.

        double x=2.5;

At this point in code, you've introduced an object named x into the scope of main(). That scope is nested inside global scope, so now you have two objects named x:

  1. x in global scope of type const double

  2. x in the scope of main() of type double

The local x hides the global x. If you want to access the global x inside main(), you can refer to it as ::x.

    std::cout << "2) x=" << x << std::endl;
    double x=3.5;  //uncommented

No you're trying to introduce another object named x into the scope of main(). This is not possible, there already is one x in that scope, so it fails.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thanks! Ok, turns out the question has nothing to do with "global" variables, but more my lack of understanding about redeclaration within nested scopes. e.g question could be equally posed as http://pastebin.com/raw.php?i=V5xni19M For that code, it just seems conceptually weird to me that the compiler allows me, in the second scope, to define a variable with the exact same type and name as one that already exists (I haven't exited first scope yet). Is that just me? Seems like that could cause problems in bigger projects, and it's something I'll definitely be weary of now. – badger5000 Oct 11 '13 at 15:01
  • @JohnnyLyco While it can lead to confusion at times, it's a fundamental property of scopes in C++. In a way, it's just one more reason to avoid globals in general. – Angew is no longer proud of SO Oct 11 '13 at 15:02
1

The second x is not a redefinition. It is hiding the global x. This is something to watch our for particularly when dealing with inheritance:

  struct Base 
  {
      void AwesomeFunction() { }
  };

  struct Derived : public Base
  {
      // This definition 'hides' Base::AwesomeFunction
      void AwesomeFunction() { }
  };

This hiding is only allowed because the second x is in a smaller scope than the global x. You get a redfinition error for the third x because the third and the second x are at the same scope 'level'.

thelamb
  • 486
  • 3
  • 10
1

Use ::x to access the global variable from your program. Right now you are making a local variable and a global. When you first print x it can't find a local one so it assumes you meant the global. After you make your local x it no longer defaults to the global.

Steven
  • 172
  • 3
  • 9
1

What happens in your code is that the local variable takes precedence over the global variable if they take up the same name. You can use your global variable in any block throughout the program, while the local one will be disposed of at the end of its block (main). The compiler won't however let you declare two local variables of the same name in one block.

Or Cyngiser
  • 1,027
  • 1
  • 12
  • 16
1

Declarations at an inner scope (like main) are allowed to shadow declarations at an outer scope (like file scope). Your third declaration of x is at the same scope as your second, so that is a redeclaration error.

john
  • 85,011
  • 4
  • 57
  • 81
1

You're not redefining the global variable; you're defining a separate local variable with the same name.

C++ allows you to reuse a name to declare something else in a narrower scope like this; technically, the declaration in the inner scope hides the one in the outer scope so that, between the declaration and the end of the function, x refers to the local variable. You can still access the global variable by qualifying it with its namespace: ::x.

The third declaration would try to reuse the name in the same scope, which is not allowed.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644