Understanding function scopes.

Hi all! I'm learning C++ with Jumping Into C++ by Alex Allain. After having read the functions chapter, I thought I understood how the scope of functions worked. However, when moving on to the next chapter about how to build algorithms, he gives some example code using functions to print prime numbers.

The code is below, coupled with my own (primitive) understanding of how it works in comments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

using namespace std;

// note the use of function prototypes
bool isDivisible (int number, int divisor);
bool isPrime (int number);

int main ()
{
    for ( int i = 0; i < 100; i++ )
    {
    if ( isPrime( i ) ) //i = 0, from the for loop
    {
    cout << i << endl;
    }
    }
}

bool isPrime (int number) //number is set as 0, from i = 0 in int main for loop
{
    for ( int i = 2; i < number; i++) //number = 0, i = 2, from the for loop
    {
    if ( isDivisible( number, i ) ) // 0, 2
    {
    return false;
    }
    }
    return true;
}

bool isDivisible (int number, int divisor) //number = 0, from the for loop in int main? divisor = 2, from the for loop in isPrime
{
return number % divisor == 0;
}


My struggle in understanding is due to the book saying the following:
"The visibility of a variable is called its scope. The scope of a variable simply means the section of code
where the variable’s name can be used to access that variable. Variables declared within a function are
available only in the scope of the function—when the function itself is executing. Variables declared in
the scope of one function are not available to other functions that are called during execution of the
first function. When one function calls another, the new function’s variables are the only ones available."

If this is true, how does isDivisible store isPrime's value for "number?" Shouldn't isPrime's "number" value be out of scope for isDivisible? Or can they share the variable because isDivisible is used inside of isPrime?
The isDivisible() function is passed the value of isPrime's variable and also the value of the variable i. As such, the scope of int number and int divisor in isDivisible() are local to that function.
Right, I understand the 'how' of it working, but not the 'why.' The book states that variables declared inside one function are NOT available to other functions. As you can see, "number" is declared for isPrime inside of int main. In bool isPrime, isDivisible is somehow able to read isPrime's number value despite it being from a different function, and despite the book saying this shouldn't be possible.

"Variables declared in the scope of one function are not available to other functions that are called during the execution of the first function."

I feel like I'm misinterpreting the book because clearly that's what the program is doing, but it's giving me a huge mental hangup.

So... true or false:
Functions used inside of other functions can borrow variables from functions the book says should be out of scope? Sorry if my failed logic is hard to understand. I feel like the book is giving mixed messages, or I simply don't understand what he's saying.
Last edited on
What you are talking about is values. Functions can pass values to other functions. number in isPrime is not the same variable as number in isDivisible but they could have the same value.
As you can see, "number" is declared for isPrime inside of int main. In bool isPrime, isDivisible is somehow able to read isPrime's number value despite it being from a different function, and despite the book saying this shouldn't be possible.


Your misunderstanding is that there are 2 separate variables named 'number' here.
1) The parameter to 'isPrime' (declared on line 20)
2) The parameter to 'isDivisible' (declared on line 32)

Even though these variables have the same name... they are completely different.. and store two completely independent values.

When you are using 'number' in the isDivisible function, you are not using isPrime's variable... you are using isDivisible's variable which just happens to have the same name.


So your book is correct. A variable is "invisible" outside of its current scope. isDivisible does not "see" isPrime's variables because it is outside of that scope.

What's happening is that isPrime is passing data into isDivisible through the use of parameters. Take a look at lines 13 and 24, where you call these functions:

if ( isPrime( i ) )

This is inside main.
Here, you are calling isPrime and giving it a single parameter... i
If you look at the isPrime function, you'll see that this parameter is named 'number'.

So this line basically does this:
 
isPrime__number = main__i;

Before executing the code inside of isPrime.


Then again on line 24, you have isPrime calling another function:
 
if ( isDivisible( number, i ) )


Here, you are passing in 2 parameters: number and i
Taking a look at isDivisible, these 2 parameters are named number and divisor.

So again, this basically does this:
1
2
isDivisible__number = isPrime__number;
isDivisible__divisor = isPrime__i;
Thanks, I forgot that variable names can be duplicated as long as they're separate functions. Here's my question now: how does " if ( isDivisible( number, i ) ) " on line 24 get its value for "number?" I assume the i gets its value from the for loop on line 22, but I don't see where isDivisible's copy of "number" gets a value. Does it borrow isPrime's value for number because it's declared inside of isPrime?

Thanks so much for all the help so far.
The compiler pushes the value of the variable on the stack before it calls the function. When the function runs, the parameter variable is popped off of the stack into that function's variable.
Forget about this "borrow" thing. There's no borrowing going on -- you might be just confusing yourself.


Think of a variable as a small box. It holds a single value:

 
int foo = 5;


Here we have a box named 'foo', and inside that box is the number 5.

 
int bar = foo;


Now we are creating another box named 'bar'. Inside that box, we take whatever value is inside foo and copy it so it is also inside bar. So now, both our foo and bar boxes contain the number 5.

 
foo -= 1;


Now we take whatever is inside foo (5), subtract it by 1, and put that value back in foo.
So now our foo box contains a value of 4, and our bar box still contains a value of 5.



Parameters are the same as variables. Only instead of assigning them with the = operator, the assignment is implicit:

1
2
3
4
5
6
7
8
9
10
void func(int param)
{
    cout << param;
}

int main()
{
    int foo = 6;
    func(foo);
}


Here, main() has a box named foo that has 6 in it.
Then, when it calls the 'func' function, it is giving the contents of foo as a parameter. This means that the contents of the 'foo' variable is being copied into the contents of our 'param' variable in func.

So now.. both func's 'param' box and main's 'foo' box both contain the number 6.

Then when func sends that value to cout, a "6" is printed on screen.




So now to answer your question more directly:
how does " if ( isDivisible( number, i ) ) " on line 24 get its value for "number?"


"number" is the parameter. It gets its value from whatever was passed in when the function was called. In your case... main() is calling it. Take a look at line 13:
 
if ( isPrime( i ) )


main is giving the contents of its 'i' box as the parameter. Therefore, isPrime's 'number' box will contain the same value as whatever was inside of main's 'i' box at the time of the call.
Last edited on
Wonderful explanation, thank you so much for taking the time to help. Marking this as solved!
Topic archived. No new replies allowed.