Show Lecture.VariableScope as a slide show.
CS253 Variable Scope
Variable Scope
- There are several variable scopes:
- Global (outside of any function or method)
- Function (or method)
- Even smaller than function (for, while, if,
{
}
)
- Class scope (not going there, yet)
- Generally, declare a variable in the most restricted scope that
you can manage.
- Old-school programmers declare all of their variables at the
start of a function.
- They also usually initialize those variables to a useless value.
- Don’t worry—they won’t be around long.
Global variables
int alpha = 42; // global scope, static duration
int main() {
cout << ++alpha << '\n';
}
43
- Global variables are evil. 😈
- I’m sure that we can find situations where they cause no problem,
or are even necessary. Let’s not focus on that.
Example of evil
int i; // ☠️ ☠️ ☠️
void foo() {
for (i=0; i<5; i++)
cout << "In foo, i=" << i << '\n';
}
int main() {
for (i=0; i<3; i++) {
cout << "In main, i=" << i << '\n';
foo();
}
}
In main, i=0
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
Slightly less evil—function scope
void foo() {
int i;
for (i=0; i<5; i++)
cout << "In foo, i=" << i << '\n';
}
int main() {
int i;
for (i=0; i<3; i++) {
cout << "In main, i=" << i << '\n';
foo();
}
}
In main, i=0
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
In main, i=1
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
In main, i=2
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
Downright good—loop scope
void foo() {
for (int i=0; i<5; i++)
cout << "In foo, i=" << i << '\n';
}
int main() {
for (int i=0; i<3; i++) {
cout << "In main, i=" << i << '\n';
foo();
}
}
In main, i=0
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
In main, i=1
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
In main, i=2
In foo, i=0
In foo, i=1
In foo, i=2
In foo, i=3
In foo, i=4
A variable declared in an if statement only exists within
the if statement:
if (auto uid = getuid())
cout << "Non-zero uid " << uid << ": not super-user\n";
else
cout << "Zero uid " << uid << ": super-user\n";
Non-zero uid 1509: not super-user
Same for while loops:
while (int v = (rand() & 0b111))
cout << v << ' ';
7 6 1 3 1 7 2 4 1 5 2 3 2 3 3 6 4 2 4
Global constants
constexpr int days_in_week = 7;
const auto starting_time = time(nullptr);
int main() {
cout << "Days/year: " << 52*days_in_week << '\n'
<< "Secs: " << starting_time << '\n';
return 0;
}
Days/year: 364
Secs: 1732264420
Global variables are evil, but global constants cause no problems.
Somewhat constant globals
string program_name;
void die_screaming() {
cerr << program_name << ": fatal error!\n";
exit(1);
}
int main(int, char *argv[]) {
program_name = argv[0];
die_screaming();
}
./a.out: fatal error!
- Not really a global variable,
but not quite a global constant, either.
- Since it’s only changed once, early in the program,
it doesn’t really increase program complexity.
Function scope
int main() {
double pi = 355.0/113;
cout << pi << '\n';
return 0;
}
3.14159
- It’s a variable.
- It’s in a function.
- Not too mysterious.
Local scope
int main() {
double pi = 355.0/113;
cout << pi << '\n';
if (pi < 5) {
auto tau = pi*2;
cout << tau << '\n';
}
return 0;
}
3.14159
6.28319
pi
has function scope
tau
has even more limited scope—just that if statement.
- I want to name the variables π & τ but that doesn’t work, yet.
Declaration before use
Don’t get fooled by words like “global”. You still have to
declare a variable before you use it.
const char spread1[] = "peanut butter";
int main() {
cout << spread1 << '\n';
}
peanut butter
int main() {
cout << spread2 << '\n';
}
const char spread2[] = "jelly";
c.cc:2: error: 'spread2' was not declared in this scope
Sure, spread2
is global, but poor main() didn’t know anything
about it, yet.
Shadowing
Shadowing: an inner scope symbol shares a name with an outer scope symbol.
string s = "Larry";
int main() {
cout << "1: " << s << '\n';
string s = "Moe";
cout << "2: " << s << '\n';
if (!s.empty()) {
string s = "Curly";
cout << "3: " << s << '\n';
}
cout << "4: " << s << '\n';
return 0;
}
1: Larry
2: Moe
3: Curly
4: Moe
- Don’t do this unless you have a real good reason to.
g++ -Wshadow
warns you about this.
Names
Johann Gambolputty de von Ausfern-schplenden-schlitter-crasscrenbon-fried-digger-dingle-dangle-dongle-dungle-burstein-von-knacker-thrasher-apple-banger-horowitz-ticolensic-grander-knotty-spelltinkle-grandlich-grumble-meyer-spelterwasser-kurstlich-himbleeisen-bahnwagen-gutenabend-bitte-ein-nürnburger-bratwustle-gerspurten-mitzweimache-luber-hundsfut-gumberaber-shönendanker-kalbsfleisch-mittler-aucher von Hautkopft of Ulm
- The length of a variable name should be proportional to its scope.
- small scope, short name
- big scope, long name
- The name
i
is fine for a five-line for-loop.
buf
seems ok for a local buffer in a short function.
- On the other hand, a global string that contains the program
name should be called something like
program_name
.