Search

4.1a — Local variables, scope, and duration

The following section builds on section 1.4b -- a first look at local scope.

When discussing variables, it’s useful to separate out the concepts of scope and duration. A variable’s scope determines where a variable is accessible. A variable’s duration determines where it is created and destroyed. The two concepts are often linked.

Variables defined inside a function are called local variables. Local variables have automatic duration, which means they are created (and initialized, if relevant) at the point of definition, and destroyed when the block they are defined in is exited. Local variables have block scope (also called local scope), which means they enter scope at the point of declaration and go out of scope at the end of the block that they are defined in.

Consider this simple function:

Because i and d were defined inside the block that defines the main function, they are both destroyed when main() is finished executing.

Variables defined inside nested blocks are destroyed as soon as the nested block ends:

Variables defined inside a block can only be seen within that block. Because each function has its own block, variables in one function can not be seen from another function:

This means functions can have variables or parameters with the same names as other functions. This is a good thing, because it means we don’t have to worry about naming collisions between two independent functions. In the following example, both functions have variables named x and y. These variables in each function are unaware of the existence of other variables with the same name in other functions.

Nested blocks are considered part of the outer block in which they are defined. Consequently, variables defined in the outer block can be seen inside a nested block:

Shadowing

Note that a variable inside a nested block can have the same name as a variable inside an outer block. When this happens, the nested variable “hides” the outer variable. This is called name hiding or shadowing.

If you run this program, it prints:

10
5

In the above program, we first declare a variable named apples in the outer block. Then we declare a different variable (also named apples) in the nested block. When we assign value 10 to apples, we’re assigning it to the nested block apples. After printing this value, nested block apples is destroyed, leaving outer block apples with its original value (5), which is then printed. This program executes the exact same as it would have if we’d named nested block apples something else (e.g. nbApples) and kept the names distinct (because outer block apples and nested block apples are distinct variables, they just share the same name).

Note that if the nested block apples had not been defined, the name apples in the nested block would still refer to the outer apples, so the assignment of value 10 to apples would have applied to the outer block apples:

The above program prints:

10
10

In both examples, outer block apples is not impacted by what happens to nested block apples. The only difference between the two programs is which apples the expression apples = 10 applies to.

Shadowing is something that should generally be avoided, as it is quite confusing!

Rule: Avoid using nested variables with the same names as variables in an outer block.

Variables should be defined in the most limited scope possible

For example, if a variable is only used within a nested block, it should be defined inside that nested block:

By limiting the scope of a variable, you reduce the complexity of the program because the number of active variables is reduced. Further, it makes it easier to see where variables are used. A variable defined inside a block can only be used within that block (or nested sub-blocks). This can make the program easier to understand.

If a variable is needed in an outer block, it needs to be declared in the outer block:

This is one of the rare cases where you may need to declare a variable well before its first use.

Rule: Define variables in the smallest scope and as close to the first use as possible..

Function parameters

Although function parameters are not defined inside the block belonging to the function, in most cases, they can be considered to have block scope.

The exception case is for function-level exceptions, which we’ll cover in a future section.

Summary

Variables defined inside functions are called local variables. These variables can only be accessed inside the block in which they are defined (including nested blocks), and they are destroyed as soon as the block ends.

Define variables in the smallest scope that they are used. If a variable is only used within a nested block, define it within the nested block.

Quiz

1) Write a program that asks the user to enter two integers, the second larger than the first. If the user entered a smaller integer for the second integer, use a block and a temporary variable to swap the smaller and larger values. Then print the value of the smaller and larger variables. Add comments to your code indicating where each variable dies.

The program output should match the following:

Enter an integer: 4
Enter a larger integer: 2
Swapping the values
The smaller value is 2
The larger value is 4

2) What’s the difference between a variable’s scope and duration? By default, what kind of scope and duration do local variables have (and what do those mean)?

Quiz solutions

1) Show Solution

2) Show Solution

4.2 -- Global variables and linkage
Index
4.1 -- Blocks (compound statements)

153 comments to 4.1a — Local variables, scope, and duration

  • Fateh Chadha

    Hi in this example. the value inside the if statement (apples >= 5) still refer to the apples in outer block? or does it now refer to the apples in nested block once we define it?

  • totoro

    is that fine?

    • Hi Totoro!

      * Line 3 and 4 should be moved inside of @main, because they're not used elsewhere.
      * Line 8, 9: Initialize your variables with uniform initialization.

      Your code doesn't swap the values. Try completing the following code

  • Hi,

    My final solution is thus:

    I did try putting the calls to input the integers in separate routines but it confused issues and put them out of scope.  It seems that it really is a case of simple is best.

    • Hi Nigel!

      Line 10, 14, 22: Initialize your variables with uniform initialization.

      If you had trouble moving the input code into separate functions you might not understand functions or scopes correctly. If you share the code you've tried I'll gladly point out what's wrong.

      • The problem arises at lines 32 and 33.

        • Line 24, 25: You're creating uninitialized variables, you should never do that.

          The problem is that you're using uninitialized variables (line 26, 27). To fix this, you have to initialize them.
          But you don't need to, because @getDigit1 and @getDigit2 don't even use their parameters. You should declare the parameters of @getDigit1 and @getDigit2 to be local variables instead.

          And change main to

          • Ah yes, got it now, thanks.  I can see where I was going wrong.

          • So I end up with this, which functions as it should and follows the target of the question:

            Thank you again.  I know I could have just done everything within main() but I think it is much tidier and easier to read if functions are separated.

  • Aditi

    My solution

    • Hi Aditi!

      * Line 6: Initialize your variables with uniform initialization
      * Line 15, 16 and line 24, 25 are equivalent, move them outside of the conditional blocks, that's what the swap is for.

  • Tulsi das

    Hi Henry,

    If the program is for purpose only the display to user than it is 100% correct but if need to extend the program and later again use these number than it would required a swap.

  • Tubbs

    /******************************************************************************
    Q: Any errors here or could I do better in certain coding practices anywhere?

    *******************************************************************************/

    • nascardriver

      Hi Tubbs!

      Good job solving the quiz!

      Suggestions:
      * Initialize your variables with uniform initialization.
      * @userSmallInput and @userBigInput2 are almost equivalent, don't repeat yourself.
      * Try limiting your lines to 80 characters in length. Most editors have an options to display a vertical line.
      * Line 26, 35: Repetition of "Smaller Integer:[...]", don't repeat yourself.
      * @main The variables in there are most likely destroyed before Line 52, Line 53 is just where they go out of scope.

      • Tubbs

        Ok thanks for the reply but I didn't get these things that you said:
        @userSmallInput and @userBigInput2 are almost equivalent, don't repeat yourself. (I think you meant I can save some space by using 1 function and calling it twice?)
        Line 26, 35: Repetition of "Smaller Integer:[...]", don't repeat yourself.
        and I was wondering where the variables are destroyed in:
        @main The variables in there are most likely destroyed before Line 52, Line 53 is just where they go out of scope.

        • nascardriver

          > you meant I can save some space by using 1 function and calling it twice?
          Exactly. Not only that but you'll also have an easier time if you decide to update the function, because otherwise you'd need to change the same thing in two places.

          > Repetition of "Smaller Integer:[...]",

          Lines 6-8 are equivalent to lines 18-20, move those lines outside the if-else blocks.

          > I was wondering where the variables are destroyed
          They can be destroyed as soon as they aren't used anymore. The return statement doesn't use any of those variables so they could be destroyed before the return is encountered.

  • Henry

    Look at my code, I used just if else statement and i still got a desired result

    • nascardriver

      Hi Henry!

      Fist of all, nice code!

      You got away without a temporary variable, because you didn't actually swap the values, you just printed them in a different order.
      You should be able to run

      at the end of @main and get the expected results, which is not the case with your code.

      • Henry

        But the code is syntactically correct?

        • nascardriver

          Yes, if it wasn't you wouldn't have been able to compile it. It's behavior is also correct. So mission accomplished, but this quiz is about the way to the target, not the target itself.

          Filling that gap is the quiz.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]