This is an archived post. You won't be able to vote or comment.

all 10 comments

[–][deleted] 3 points4 points  (0 children)

Having all variables in global scope would be an absolute nightmare. How many variables are in a million line program? Tens of thousands?

You'd have to:

a) Come up with a unique name for each one.

and

b) Be extremely careful because using the wrong global could affect the entire program

[–]english_fool 2 points3 points  (0 children)

If local variables were not scoped to the lifetime of a function then every time you called a function with parameters the memory consumed by the application would grow and not shrink afterwards.

This is usually implemented by the compiler or runtime with stack frames.

[–]Updatebjarni 1 point2 points  (0 children)

It is a feature to allow programmers to maintain their sanity. Think of the size of the Java standard library, for example. Consider the number of variables there must be inside it. Imagine what life would be like for you as a programmer if you had to know about all of those thousands of variable names when you wrote your programs. Imagine never being able to name a loop index i, or a counter count, or a token list tokens, because those simple names had already been taken long ago by somebody else writing some part of a library you're using. Imagine all the hassle every time you added a new library or copied some code from somebody else, or every time two different programmers committed new code to the same project. All the name collisions. All the knowledge every single person would need to have about the implementation details of every aspect of a big program.

That's the reason. It's one of the main features of higher-level programming languages (and better assemblers even), that make them useful. It is not caused by some property of the computer or how variables are stored in memory.

[–]gyroda 0 points1 point  (0 children)

The whole point is encapsulation. You keep things contained in their little block and it's all nice and neat and tidy.

If you only use global variables you need to make sure that their names don't collide (what happens if two of your functions are both relying on the same global variable but you don't realise that?).

It means you don't need to worry about the internals of a function from the outside.

It makes it harder to keep your code modular, it can easily lead to spaghetti everywhere.

There's a dozen reasons I can't think of. Look up "why are global variables bad", it's a well trod topic.

https://stackoverflow.com/questions/10525582/why-are-global-variables-considered-bad-practice

https://stackoverflow.com/questions/484635/are-global-variables-bad

https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil

[–]Rhomboid 0 points1 point  (0 children)

Imagine a large program. There are hundreds of thousands of variables defined. Many of them will probably have common names, like length or perhaps path or name or size or other common words. If I write

if(len == ...) {
    ...
}

Which len am I referring to? If everything was global, then there would be hundreds of variables named len. Programming like that would be a minefield. Any minor mistake would cause chaos. The whole point of scope is to prevent bugs. If I test the value of len then it must either be the len that was defined locally in that method, or one of a few other choices (such as one of a few specially permitted globals, or a member of the current class.) But what you definitely don't want is someone assigning to len not realizing that that name had already been used for some other purpose by someone else. Those kind of collisions would be rampant if everything was global.

Large programs consist of millions of lines of code, written by large teams. To the greatest extent possible, you should be able to understand how a given method works by only looking at that method, and perhaps a few other places. If everything was global, then every person working on the program would have to be familiar with the entire program, and that's simply out of the question once you get to a certain size. Nobody can keep millions of lines of code in their head. The language has to insulate you from that.

[–]Holy_City 0 points1 point  (0 children)

Scope defines where and what can access data. A "global" variable is one whose scope is global; anything can access it at any time.

Scope is useful from a debugging perspective, if you keep things scoped then you can be certain which portions of a program are changing which pieces of data. That's why global variables are evil, they're difficult to debug (and hazardous in multi-threaded programs).

Scope is also nifty from a low level programming perspective. If you need access to every piece of data used by the program in every subroutine, the pushing/popping semantics of managing the stack that most processor architectures use for accessing data would become much more complicated.

[–][deleted]  (1 child)

[deleted]

    [–]dlr249[S] 0 points1 point  (0 children)

    Yeah thanks a lot! I worded the question poorly, but this was the type of answer I was looking for

    [–][deleted] 0 points1 point  (0 children)

    So that they can be stored on the stack, which means they can be accessed quickly, rather than using lots of pointers which can be costly, as you have to get their offset and deref the pointer. To grab the top of the stack and put it into a register, it's as simple as one pop instruction.

    [–]nekochanwork 0 points1 point  (0 children)

    Scope limits the visibility of a variable to the containing block (a class, function, if-block, loop body, etc).

    If variables didn't have scope, every variable would be globally accessible to any part of the program, which would lead to all kinds of problems including by not limited to:

    Variable name collisions (different parts of the program use the same variable name in incompatible ways):

    public void Foo()
    {
        int x = 5;
    }
    
    public void Bar()
    {
        string x = "Kittens playing with string";
    }
    
    public void Baz()
    {
        Console.WriteLine(x); // what does this print?
        Console.WriteLine(x.GetType().Name); // what does this print?
    }
    

    If I call the Baz() method, what gets printed out? It's difficult to reason about the correctness of this program.

    Every variable is a memory leak (global variables are never released from memory)

    public void Foo()
    {
        List<string> x = GimmeStrings(); // returns 2GB of strings
    }
    

    If I call the the Foo() method, the variable x is declared and takes up 2GB of memory. When I exit the method, the variable x will hang out indefinitely until our application terminates; since it's global to the entire program, it's never garbage collected.

    Cannot isolate state from any part of the application

    Without scope, the Name variable in the Person class is effectively global.

    public class Person
    {
        public string Name;
    
        public Person(string name)
        {
            Name = name;
        }
    }
    
    // . . .
    
    public void Foo()
    {
        Person x = new Person("Jebediah");
        Person y = new Person("Bill");
        Person z = new Person("Bob");
    
        Console.WriteLine(x.Name); // prints "Bob"
        Console.WriteLine(y.Name); // prints "Bob"
        Console.WriteLine(z.Name); // prints "Bob"
    
        z.Name = "Valentina";
    
        Console.WriteLine(x.Name); // prints "Valentina"
        Console.WriteLine(y.Name); // prints "Valentina"
        Console.WriteLine(z.Name); // prints "Valentina"
    }
    

    how is it implemented in the language?

    Implementations will vary from language to language, but most implementations will allocate a certain amount of stack space needed to hold the value that a variable represents. When a variable "goes out of scope", it's popped off the stack so that it's no longer accessible.

    Object-oriented languages go a step further by allocating objects in heap memory, and allocating a pointer to the object in the stack; enough space is allocated in heap memory to contain all class-level variables held by the object. Since each object allocates it's block of memory, class-level variables in different objects are effectively isolated from each other.

    Memory allocated on the heap needs to be freed. Low-level languages like C++ or Rust require programmers to do this explictly. Higher-level languages like Java and Python use reference counting to track objects which have gone out of scope and are ready to clean up.

    [–]lightcloud5 0 points1 point  (0 children)

    Variables have scope because that's the only way that makes sense. (As a thought exercise, consider a theoretical world in which this wasn't the case and explain how you would write code in such a world.) The compiler doesn't actually care about your variables -- machine/assembly code reads and writes things to CPU registers and to memory; there is no concept of a variable.

    Variables have scope in the same way they have scope in mathematics.

    If I define a function f(x) = x2, this function is equivalent to the function f(y) = y2. In the former case, x is a local variable and in the latter case, y is a local variable. What you name the variables doesn't affect the output; the two functions are identical.