Variables and Memory
What a variable really is, where it lives, and how to think about it as a labelled box in RAM
A variable in C is a name attached to a piece of memory. Behind the friendly name is a fixed-size box of bytes at a specific address.
That mental model — variable = labelled box in memory — will guide every chapter from now on.
Declaring a variable
The minimum recipe for a variable is:
type name; // declare, value is undefined
type name = value; // declare and initializeExamples:
Three things happen on the line int age = 30;:
- Reserve memory. The compiler picks 4 bytes (on a typical system) somewhere in memory to hold the value.
- Bind the name. From now on, every occurrence of
agein this scope refers to those 4 bytes. - Initialize. The bit pattern for
30is written into those bytes.
Picture it
After the two declarations above, memory might look like:
Address Variable Value (decimal)
---------- --------------- --------------
0x7ffc...0 age 30
0x7ffc...4 year_of_birth 1995Each box is 4 bytes. The actual addresses are not predictable across runs — they depend on the OS, the architecture, and security features like ASLR. But the shape is reliable.
Assignment versus declaration
Once a variable has been declared, you can change its value with the
= operator. The type is not repeated.
That last line, score = score + 5;, is a great example of
sequential thinking. The right-hand side is evaluated first,
producing the new value 15, which is then stored back into
score. C is full of these "read, compute, write" patterns.
Read versus write
When score appears on the left of =, you are writing to
it. When it appears on the right, or in an expression, you are
reading from it.
score = score + 5;
^ ^
| +-- read
+------------ writeNaming variables
Variable names in C:
- May contain letters, digits, and underscores
_. - Must not start with a digit.
- Are case-sensitive —
Score,score, andSCOREare three different variables. - Cannot collide with C keywords (
int,if,return, ...). - Should be descriptive.
nis fine for a loop counter;scoreis better thansfor a score.
int score; // good
int playerScore; // also fine (camelCase)
int player_score; // fine (snake_case — more common in C)
int 1st_score; // ERROR: starts with a digit
int return; // ERROR: keywordA style note
The C ecosystem traditionally uses `snake_case` for variable and function names (`player_score`, `compute_total`). Pick a style and stay consistent within a project. Consistency matters more than the exact convention.
What "uninitialized" really means
If you declare a variable without giving it a value:
int x;
printf("%d\n", x); // prints whatever happened to be in memory…the compiler reserves the memory but does not zero it. The contents are whatever was left there by the previous use of those bytes. The value you read is undefined behavior — the program may print anything, including different values on different runs. Always initialize.
Try it (the exact number printed below is unpredictable and varies between runs and compilers):
Modern compilers will often warn you about this. Pay attention.
Constants
Sometimes you want a name that refers to a fixed value that must never change. There are two common ways.
const marks a variable read-only after initialization:
const int SPEED_OF_LIGHT = 299792458; // m/sThe compiler will reject any attempt to write to it later.
#define is a textual constant handled by the preprocessor:
#define MAX_PLAYERS 8Both are useful; const is more strongly typed and easier to debug,
so prefer it unless you specifically need a preprocessor macro.
Memory diagram practice
Predict the final values of a and b after this program runs, then
run it to check:
This is the classic swap idiom. Trace it with a table:
| step | a | b | tmp |
|---|---|---|---|
| start | 1 | 2 | — |
int tmp = a; | 1 | 2 | 1 |
a = b; | 2 | 2 | 1 |
b = tmp; | 2 | 1 | 1 |
A common rookie mistake is to try a = b; b = a; without a
temporary — but by the time the second line runs, a already holds
the new value, so you copy it back into b and lose the original.
Always think what's in each box, right now?
Why memory matters even for int
A int on most systems is 4 bytes. That means it can hold values
roughly between -2,147,483,648 and +2,147,483,647. Go above that
and the value wraps around — a phenomenon called integer
overflow.
This is a small but profound lesson: in C, every variable has a finite number of bits. There are no infinite integers, no arbitrary precision. You have to choose a type that fits your data.
We'll meet more types in the next chapter.
Challenge: temperatures
A variable celsius is set to 25. Compute the equivalent Fahrenheit value using the formula F = C * 9 / 5 + 32 and print exactly:
25 C = 77 F
Which statement best describes a variable in C?
A keyword reserved by the compiler.
An object that grows and shrinks automatically based on the value assigned to it.
A name bound to a fixed-size region of memory whose contents can be read or written.
A function that always returns the most recent value passed to it.
What is wrong with this code?
int x;
int y = x + 1;
printf("%d\n", y);
Nothing — y will always be 1.
The compiler will refuse to build it.
x is uninitialized, so reading it is undefined behavior; y could be anything.
y cannot be initialized from another variable.