WEBVTT X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:900000 00:00:05.300 --> 00:00:07.300 DOUG LLOYD: As you start working with functions, 00:00:07.300 --> 00:00:09.966 another thing is going to become really important to understand, 00:00:09.966 --> 00:00:12.380 which is the concept of variable scope. 00:00:12.380 --> 00:00:14.490 So scope is a characteristic of a variable 00:00:14.490 --> 00:00:18.860 that defines from which functions that variable can be accessed. 00:00:18.860 --> 00:00:24.595 >> There are two primary scopes in C, local variables and global variables. 00:00:24.595 --> 00:00:27.830 Now, local variables can only be accessed within the functions 00:00:27.830 --> 00:00:29.045 in which they're created. 00:00:29.045 --> 00:00:32.170 They can't be accessed by every other function that exists in your program, 00:00:32.170 --> 00:00:34.184 only the function in which it was created. 00:00:34.184 --> 00:00:36.350 Global variables, on the other hand, can be accessed 00:00:36.350 --> 00:00:37.719 by any function in the program. 00:00:37.719 --> 00:00:40.260 And the reason for that is because they're not created inside 00:00:40.260 --> 00:00:41.441 of any particular function. 00:00:41.441 --> 00:00:43.690 We declare them outside of all of the functions, which 00:00:43.690 --> 00:00:48.940 means that every function knows where it is and can access and manipulate it. 00:00:48.940 --> 00:00:52.010 >> So far in the course you've pretty much been working exclusively 00:00:52.010 --> 00:00:54.280 with local variables. 00:00:54.280 --> 00:00:58.320 Here's an example of a very, very simple main function and a very simple 00:00:58.320 --> 00:01:00.680 additional function that we've written. 00:01:00.680 --> 00:01:03.180 In this case, x, which I've colored green just 00:01:03.180 --> 00:01:07.400 to highlight the locality or the scope of that variable, 00:01:07.400 --> 00:01:09.240 is local to the function triple. 00:01:09.240 --> 00:01:12.300 main cannot refer to x at all. 00:01:12.300 --> 00:01:14.259 It doesn't know what it is. 00:01:14.259 --> 00:01:17.050 No other function, in fact, if we had additional functions in here, 00:01:17.050 --> 00:01:19.360 could refer to x. 00:01:19.360 --> 00:01:23.520 >> Similarly, results which I've colored blue, is local only to main. 00:01:23.520 --> 00:01:26.980 Only main knows what the variable result is. 00:01:26.980 --> 00:01:30.010 triple cannot use it. 00:01:30.010 --> 00:01:32.580 >> Now as I mentioned, global variables do exist. 00:01:32.580 --> 00:01:35.575 If you declare that variable outside of any function, 00:01:35.575 --> 00:01:38.290 all of the functions in the program can refer to it. 00:01:38.290 --> 00:01:44.010 So in this case I've highlighted in green a global variable declaration. 00:01:44.010 --> 00:01:45.830 In this case, the variable being declared 00:01:45.830 --> 00:01:48.720 is called global, just to be extremely clear about it. 00:01:48.720 --> 00:01:49.720 It is of type float. 00:01:49.720 --> 00:01:52.940 And I assign it the value 0.5050. 00:01:52.940 --> 00:01:58.080 >> You'll notice that in main and in triple, I am able to refer to global. 00:01:58.080 --> 00:02:03.480 And in fact, if I go through the program as indicated, main first calls triple, 00:02:03.480 --> 00:02:10.440 triple multiplies global by 3, which sets its value to 1.5-something, 00:02:10.440 --> 00:02:16.080 1.51 or something like that, and then main also prints out the value 00:02:16.080 --> 00:02:16.620 of global. 00:02:16.620 --> 00:02:24.424 So main will not print out 0.5050, it will print out global times 3, 1.51. 00:02:24.424 --> 00:02:27.340 So you've got to be careful when you're working with global variables. 00:02:27.340 --> 00:02:30.260 While they're very flexible in being able to pass information 00:02:30.260 --> 00:02:32.650 around so that every function can use it, 00:02:32.650 --> 00:02:34.580 it also can have some dangerous consequences 00:02:34.580 --> 00:02:38.770 if one function changes the value of a variable 00:02:38.770 --> 00:02:42.360 before you expect it to be changed. 00:02:42.360 --> 00:02:44.200 >> Why does this distinction matter? 00:02:44.200 --> 00:02:48.070 Why do we care whether some variables are local and others are global? 00:02:48.070 --> 00:02:53.880 Well, for the most part, local variables in C are what's called passed by value 00:02:53.880 --> 00:02:56.087 when we make a function call. 00:02:56.087 --> 00:02:56.920 What does that mean? 00:02:56.920 --> 00:03:00.880 >> Well, when a variable is passed by value, the callee, which 00:03:00.880 --> 00:03:04.350 is another way of saying the function that is receiving the variable that 00:03:04.350 --> 00:03:08.465 gets passed in as an input, it actually doesn't receive that variable itself. 00:03:08.465 --> 00:03:12.490 It receives its own copy of it to work with. 00:03:12.490 --> 00:03:14.350 This is a really important distinction. 00:03:14.350 --> 00:03:18.250 We just saw a second ago that with global variables, 00:03:18.250 --> 00:03:23.240 if we manipulate the global variable in one function, the effect 00:03:23.240 --> 00:03:26.390 in that one function carries through to every other function. 00:03:26.390 --> 00:03:28.920 >> But with local variables, that's not true. 00:03:28.920 --> 00:03:32.060 Each function when it receives variables as input 00:03:32.060 --> 00:03:36.367 receive copies of those variables, not the variables themselves. 00:03:36.367 --> 00:03:37.825 So what is the side effect of that? 00:03:37.825 --> 00:03:40.450 That means that the variable in the caller, the function that 00:03:40.450 --> 00:03:45.600 is making the function call, is unchanged unless you override it. 00:03:45.600 --> 00:03:50.420 >> For example, in this code foo is not changed at all. 00:03:50.420 --> 00:03:55.450 Int foo equals 4, call triple of foo, inside of triple, 00:03:55.450 --> 00:03:58.850 we would expect that foo would be multiplied by 3 and returned, 00:03:58.850 --> 00:04:01.450 but there's actually no effect. 00:04:01.450 --> 00:04:03.460 >> Here though, a very subtle difference. 00:04:03.460 --> 00:04:06.520 This does have the effect we want. 00:04:06.520 --> 00:04:07.730 Do you see why? 00:04:07.730 --> 00:04:11.500 We're overriding foo in main this time. 00:04:11.500 --> 00:04:16.899 >> So int foo equals 4, foo equals triple foo, when we make that call, 00:04:16.899 --> 00:04:21.680 triple gets its own copy of foo, its own copy of 4. 00:04:21.680 --> 00:04:27.340 It says return 4 times 3, or whatever variable gets passed in times 3. 00:04:27.340 --> 00:04:32.109 And then we assign the return value of triple to foo again. 00:04:32.109 --> 00:04:33.650 So this actually would overwrite foo. 00:04:33.650 --> 00:04:35.816 This is the only way to do this with local variable. 00:04:35.816 --> 00:04:38.120 So now if we add another line of code here 00:04:38.120 --> 00:04:40.870 at the end of main to print out the value of foo, 00:04:40.870 --> 00:04:45.030 it would in fact print out 12. 00:04:45.030 --> 00:04:48.600 >> Variable scope is generally not too much of a problem 00:04:48.600 --> 00:04:51.190 if you name all of your variables different things. 00:04:51.190 --> 00:04:54.920 But it can get kind of nasty if the same variable name 00:04:54.920 --> 00:04:58.820 appears in multiple functions, which will happen a lot. 00:04:58.820 --> 00:05:02.130 If you ever do work in the real world where 00:05:02.130 --> 00:05:06.080 you are working on collaborative programs and people in different teams 00:05:06.080 --> 00:05:11.000 are working together to write the same program or the same set of programs, 00:05:11.000 --> 00:05:13.900 they'll frequently reuse variable names, particularly common ones 00:05:13.900 --> 00:05:18.020 like x, y, i, j, and so on. 00:05:18.020 --> 00:05:20.370 >> But when variables have the same name, scope issues 00:05:20.370 --> 00:05:23.080 can get a little trickier to parse. 00:05:23.080 --> 00:05:26.790 For example, do you know what would be printed out 00:05:26.790 --> 00:05:30.190 at the end of this particular program? 00:05:30.190 --> 00:05:31.280 Take a minute. 00:05:31.280 --> 00:05:33.382 Pause the video and read through this program. 00:05:33.382 --> 00:05:35.590 You can see at the top we have a function declaration 00:05:35.590 --> 00:05:37.350 for a function called increment. 00:05:37.350 --> 00:05:40.800 That function takes a single parameter, an integer which we call x. 00:05:40.800 --> 00:05:42.610 And it outputs an integer. 00:05:42.610 --> 00:05:44.820 That's the return type at the beginning. 00:05:44.820 --> 00:05:48.140 >> Then we have main, a couple of lines of code in main, the last of which 00:05:48.140 --> 00:05:49.250 is a print statement. 00:05:49.250 --> 00:05:51.140 And remember, that's the question here. 00:05:51.140 --> 00:05:54.240 What is actually going to be printed at the end of this function? 00:05:54.240 --> 00:05:58.110 And then we actually have the definition of increment below. 00:05:58.110 --> 00:06:01.760 >> So take a minute, step through the code, trace things out. 00:06:01.760 --> 00:06:08.100 Do you know what will be printed at the end of this particular program? 00:06:08.100 --> 00:06:08.600 >> All right. 00:06:08.600 --> 00:06:11.433 Hopefully, you've taken a few seconds to try and parse this one out. 00:06:11.433 --> 00:06:13.370 Let's do it together. 00:06:13.370 --> 00:06:16.022 >> So I've crossed out increment's declaration at the top there. 00:06:16.022 --> 00:06:17.230 It was kind of a distraction. 00:06:17.230 --> 00:06:18.570 It's not its own variable. 00:06:18.570 --> 00:06:19.879 It doesn't have its own scope. 00:06:19.879 --> 00:06:21.920 It's just a function declaration, so for purposes 00:06:21.920 --> 00:06:24.330 of trying to parse out what's happening in this program, 00:06:24.330 --> 00:06:26.660 we might as well just avoid it. 00:06:26.660 --> 00:06:29.560 >> Now we have in this case, the reason this problem is tricky 00:06:29.560 --> 00:06:34.030 is because we have local variables in both main and increment, each of which 00:06:34.030 --> 00:06:35.090 is called x. 00:06:35.090 --> 00:06:39.830 And of course the crux of this issue is trying to suss out which x gets changed 00:06:39.830 --> 00:06:41.890 and how does it get changed. 00:06:41.890 --> 00:06:46.900 So I've colored every instance of x that's local to main red. 00:06:46.900 --> 00:06:52.040 And I've colored every instance of x that's local to increment blue. 00:06:52.040 --> 00:06:55.220 >> Notice in that third line of main, y equals increment 00:06:55.220 --> 00:07:00.800 x, that increment is not being passed main's x, or the red x. 00:07:00.800 --> 00:07:03.320 It's getting passed a copy of it. 00:07:03.320 --> 00:07:06.987 And it's only going to work with that copy of it, the blue x. 00:07:06.987 --> 00:07:08.820 If you're mathematically inclined, you might 00:07:08.820 --> 00:07:14.230 have instead thought of this as x sub m for main and x sub i for increment. 00:07:14.230 --> 00:07:15.700 But it's the same idea. 00:07:15.700 --> 00:07:18.999 x sub m, or the red x's in the previous slide, 00:07:18.999 --> 00:07:21.790 are the variables that are local-- is the instance of x rather that 00:07:21.790 --> 00:07:26.900 is local to main, and x sub i, or the blue variables in the previous slide, 00:07:26.900 --> 00:07:30.760 are the instances of x that are local to increment. 00:07:30.760 --> 00:07:36.220 >> So, were you able to figure out what this function printed at the end? 00:07:36.220 --> 00:07:39.420 I'm Doug Lloyd, and this is CS50.