Lecture 18: Scope and Lifetime
Watch on YouTube →
Overview
Burton Ma explains how C differs from Java in variable scope and lifetime, covering file, block, and function prototype scope alongside automatic, static, and allocated storage duration. Through examples such as an uninitialized sum, a persistent static counter, and an array that outlives its function’s local storage, he shows how lifetime mistakes cause bugs. He also explains declarations, const variables, and how function declarations and object files support programs built from multiple C source files.
Key takeaways
- In C, a file-scope identifier is available only from its declaration onward, unlike Java class fields, which can be referenced throughout the class.
- Automatic variables are not initialized by default, so accumulators such as sum must be explicitly set to zero to avoid undefined results.
- Static storage lasts for the entire program and is initialized only once, meaning a file-scope accumulator keeps its old value between function calls.
- Returning a pointer to a local array does not extend the array’s lifetime; the pointer refers to an object that ceased to exist when the function returned.
- A function prototype allows compile-time checking before a definition is available, but linking still requires the function’s implementation in a source file or object file.
- Header files prevent duplicated, error-prone function declarations across C source files by providing a shared place for interfaces.
Chapters
- C has four scope types: file, block, function prototype, and function scope; Burton Ma focuses on the first three.
- A file-scope name is usable from its declaration onward, so a later declaration of K cannot be used earlier in the file.
- Variables and functions such as J, F, K, and main have file scope when declared outside braces.
- Function parameters and variables declared inside braces have block scope, including variables declared in a for loop.
- A loop’s local I shadows a function parameter also named I, and a block-local J can hide a file-scope J.
- In a function prototype, parameter names have function prototype scope; parameter order matters when an array length refers to an earlier parameter such as n.
- Storage duration describes an object’s lifetime, which C programmers must consider more directly than in Java or Python, where garbage collection handles object cleanup.
- C distinguishes automatic, static, allocated, and thread storage duration; thread storage is deferred because it depends on multithreading.
- Allocated storage duration puts object creation and cleanup under programmer control, and failing to release resources can cause memory leaks.
- Function parameters and block-local variables normally have automatic storage duration: they are created when their block begins and cease to exist when it exits.
- A for-loop variable I lasts for the loop, while a variable J declared inside the loop body is recreated on each iteration.
- Automatic variables are not initialized by default; the sum-of-N example produces unpredictable results until sum is explicitly initialized to zero.
- File-scope variables and variables declared with static have static storage duration, lasting for the entire execution of the program.
- Static-storage objects are initialized once before execution: numeric values become zero, pointers become null, and structures receive recursively initialized members.
- A file-scope sum accumulator retains its value across calls, so calling sum_of(10) twice returns 55 and then incorrectly accumulates to 110 unless the state is reset.
- A static variable inside a function has block scope but retains its value for the program’s lifetime, unlike an ordinary local variable.
- The count example stores a persistent value initialized to zero; passing 1 increments it, while passing 0 retrieves the current count.
- Burton Ma describes this pattern as unusual and cites the C standard-library function strtok as an example that retains tokenization state between calls.
- Allocated storage is needed when an object must persist beyond the function call that creates it; the programmer must arrange its creation and eventual cleanup.
- Returning the address of a local array is unsafe because the array’s automatic lifetime ends when its function returns, even if the memory still appears to contain usable values.
- A returned pointer still holds the array’s former address, so reading through it accesses memory whose object no longer exists and can produce unpredictable behavior.
- A declaration tells the compiler that an identifier exists and what its type is; it does not necessarily define or initialize the object.
- Uninitialized automatic declarations such as int x or int a, b, c contain indeterminate values, while explicit initializers provide known values.
- A const int must be initialized at declaration because later assignment is forbidden; const is part of the variable’s type.
- A prototype such as double max_two(double, double); lets the compiler check calls before the function definition is available; parameter names are optional in the prototype.
- The max_two example can be defined in max2.c and linked with the file containing main; compiling with GCC’s -c option produces object files such as max2.o without linking.
- A declaration alone cannot produce a complete executable: the linker needs the function definition, and header files provide reusable declarations without manually copying them into every source file.
Transcript excerpt
0:03 All right. Good afternoon, everybody. Um, so today's lecture, um, there's going to be a few, we're going to cover a few notebooks, I think, in today's lecture. Um, a lot of this should be review for many of you since you took CS 124, um, but there is some new content in here as well. Um, so the first thing we want to talk about is scope of a variable or of a of an identifier. Um, so you're used to a little bit of you've seen scope already in Java. Um, scope behaves similarly in C to Java, but there are some differences. Um, and so namely, there are different types of scope than there are in in C than there are in Java. So the scope refers to the contiguous part of your program where a name can be
0:51 used. So contiguous just means unbroken. So in C, there's four kinds of scope that you have to be aware of. So there's something called file scope, which is exactly what you think it is. It's the scope of the file. There's block scope. So you know that C and Java are block delimited languages. They use the braces to denote blocks of code. Uh, and so it turns out each one of those blocks defines a new level of scope. There's something called function prototype scope, uh, and there's something called function scope. Um, and function scope we don't really care about in this course. Uh, and function prototype scope is very simple to deal with. So we'll take a look at that very shortly. Okay, so file scope. Uh, so if you have a name, an identifier, so the name of a variable or
1:39 a function, um, if it's declared outside of a block, so not inside of a pair of braces,
This is the start of the transcript. Save this video free for the whole transcript, searchable and time-coded.
In this course
Related notes
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Burton Ma.