CS253: Software Development with C++

Fall 2020

Local Static

Show Lecture.LocalStatic as a slide show.

CS253 Local Static

Try #1

Here’s a program to generate unique student ID numbers:

unsigned long next_id() {
    unsigned long id=800000000UL;
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000001
800000001

That wasn’t very good.

Try #2

Let’s move id out of next_id():

unsigned long id=800000000UL;

unsigned long next_id() {
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000002
800000003

Better, but now we have an evil global variable. 👹

Try #3

Let’s make id static:

static unsigned long id=800000000UL;

unsigned long next_id() {
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000002
800000003

Better in that id is only visible to this file, but that’s still semi-global. Can we improve?

Try #4

Move id back to next_id(), but leave it static.

unsigned long next_id() {
    static unsigned long id=800000000UL;
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000002
800000003

Hooray! Now, id is private and persistent. 👏

Summary

Sure, it’d be better to have separate words for those distinct purposes, but the standards committee is stingy with new words—better to re-use old ones.

static global example

// Assume that getpid() is expensive, so do it only once.
static const pid_t pid = getpid();

int main() {
    cout << pid << '\n';
    cout << pid << '\n';
}
2785458
2785458

Actually, in the global scope, const implies static, so the above definition is a bit redundant.

static local example

string homedir() {
    // Assume that getpwuid() is expensive--do it only once.
    // Segfault if the lookup fails! ☹
    static string dir = getpwuid(getuid())->pw_dir;
    return dir;
}
int main() {
    cout << homedir() << '\n';
    cout << homedir() << '\n';
}
/s/bach/a/class/cs253
/s/bach/a/class/cs253

Example

char foo() {
    static char id = 'A';
    cout << "foo: returning " << id << "\n";
    return id++;
}

static auto glob = foo();

int main() {
    cout << "glob = " << glob << '\n';
    for (int i=0; i<5; i++) {
        if (i>10) {
            static char zip = foo();
            cout << "zip = " << zip << '\n';
        }
        static char bar = foo();
        cout << "bar = " << bar << '\n';
    }
    return 0;
}
foo: returning A
glob = A
foo: returning B
bar = B
bar = B
bar = B
bar = B
bar = B