CS253: Software Development with C++

Spring 2021

Variable Scope

Show Lecture.VariableScope as a slide show.

CS253 Variable Scope

made at imgflip.com

Variable Scope

Global variables

int alpha = 42;  // global scope, static duration

int main() {
    cout << ++alpha << '\n';
}
43

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

if/while scope

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: 1732257956

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!

Function scope

int main() {
    double pi = 355.0/113;
    cout << pi << '\n';
    return 0;
}
3.14159

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

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

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