C Part I · Module 2 · Values, Variables, Types and Representation
Memory, Addresses and How Objects Are Stored
Chapter 2.1 said an object occupies storage and then moved on without saying what storage is. This chapter says. You will build a picture of memory as a very large run of numbered locations, of an object as a few consecutive locations reserved to hold one value, and of an address as the number that identifies where an object begins. That picture is quietly assumed by almost everything after it — measuring a type in Chapter 2.12, laying out an array in Module 6, understanding what a function call costs in Module 5, and every single page of Module 7. It is worth more time than its length suggests, and it needs no new syntax at all: not one line of code in this chapter is anything you have not already written.
Foundation13 min readCPart IFundamentalsMemory
Part I · Module 2 · Chapter 2.2 · Memory, Addresses and How Objects Are Stored
1. The Word Chapter 2.1 Left Undefined
Chapter 2.1 established that an object has a type, holds a value, and occupies storage. Two of those three were explained. The third was used five times and never defined.
Here it is. Memory is a very large collection of storage locations, and every one of them has a number that identifies it. That is genuinely the whole idea: numbered storage.
The numbers are not decoration and they are not something the machine works out by searching. Given the number, the machine can go straight to that location. That property — being able to reach any location directly, by its number — is what makes memory useful and is why the numbers exist.
The smallest location that gets its own number is called a byte. So memory is a long run of bytes, numbered from one end to the other, and the number identifying a particular byte is its address.
2. An Object Occupies Several Bytes
One byte is small. Most values need more room than that, so most objects occupy several consecutive bytes, and the object's address is the number of the first one.
Here is the picture for a single int object named count:
address byte
──────── ──────────────────────────────
1000 ┐
1001 │ the four bytes reserved to
1002 │ hold the int object `count`
1003 ┘
1004 a different object, or nothing yet
1005 a different object, or nothing yetThree things in that picture are worth stating explicitly.
The bytes are consecutive. An object is not scattered around memory; it occupies a single unbroken run. This matters far more than it looks, and Module 6 is built on it.
The address is the start. count's address is 1000 — the number of its first byte — not a list of all four.
The numbers are labels, not something you compute. 1000 here is an arbitrary number chosen to make the picture readable. Real addresses are typically written in a notation you meet in Chapter 2.4; treat them for now as identifiers, like house numbers on a street, and nothing more.
3. Two Objects, Two Places
Chapter 2.1 finished with a program that proved two objects are genuinely separate. Here it is again, now that you can say why:
#include <stdio.h>
int main(void)
{
int count = 3;
int limit = count;
count = 9;
printf("count is %d, limit is %d\n", count, limit);
return 0;
}Output:
count is 9, limit is 3int limit = count; created a second object somewhere else in memory and copied a value into it. After that, the two have nothing to do with each other. Writing 9 into the bytes at 1000 cannot possibly change the bytes at 1004, and that is the entire explanation for output that surprised you a chapter ago.
4. Where the Addresses Come From
A reasonable question at this point: who chose 1000?
Not you. You never wrote an address anywhere in that program, and you never will for an ordinary object. Deciding where each object goes is handled for you — partly by the compiler, partly by the machinery Chapter 1.7 described as setting the program up before main is called.
This has a consequence worth absorbing now, because it is the single most common wrong assumption about addresses:
You cannot predict an object's address, and you should never write a program that depends on a particular one.
Run the same program twice and an object may well sit somewhere different. Compile it with different options and it may move. None of that is a malfunction; nothing ever promised you a location.
What is promised is the structure: whatever address an object has, it occupies a consecutive run of bytes starting there, for as long as the object exists.
5. What This Chapter Is Not Claiming
This is a mental model, and a good one, so it is worth being clear about its edges before you carry it into four more modules.
"Memory" does not necessarily mean the memory chips in your computer. C describes an abstract machine — Chapter 1.1's "behaviour, not steps" — and an address in that model is a way of identifying a location, not a promise about hardware. On an ordinary computer it usually corresponds to something physical, through several layers you do not control. In the embedded and semiconductor work Part II reaches, the relationship is a subject of its own.
An address is not simply a number you can do arithmetic on freely. It is written as a number and it behaves like one in limited, well-defined ways. Chapter 7.8 covers exactly which ways, and the answer is narrower than most people guess.
Not every object you write down necessarily occupies storage for the whole program. Objects come into existence and stop existing, and the rules are the subject of Module 9. For everything in this module, assume an object inside main exists from its declaration until the program ends — which is true of every program you have written so far.
Each of those three is a real simplification. None of them is a falsehood you will have to discard: the picture in §2 stays correct, and later chapters add to it rather than replacing it.
6. Why This Picture Is Worth Holding
It may not be obvious yet why numbered storage deserves a chapter. Here is what is coming, all of which is simply this picture applied:
- Chapter 2.12 measures how many bytes a type occupies. That question only means something once objects occupy bytes.
- Module 6 stores an array as one unbroken run of consecutive objects. Indexing is then arithmetic on positions, not a search.
- Chapter 5.7 explains what a function call sets aside and gives back.
- Module 7 introduces an object whose value is the address of another object. That sentence is either obvious or impossible, depending entirely on whether §1 and §2 of this chapter feel normal to you.
- Part II puts a hardware register at a fixed address and reaches it from C.
If any part of the picture still feels vague, this is the chapter to reread. Everything above is four ideas: memory is numbered, the unit is a byte, an object occupies consecutive bytes, and its address is the first one.
7. What You Should Be Able to Say Now
- Memory is a large run of numbered storage locations. The number identifying a location is its address.
- The smallest separately numbered unit is a byte.
- An object occupies several consecutive bytes, and its address is the number of the first one.
- How many bytes a type needs is implementation-defined — the implementation chooses and documents it.
intis commonly four bytes and is not required to be. - Two objects occupy two different runs of storage, which is why changing one cannot change the other.
- You do not choose addresses and cannot predict them. What is guaranteed is the structure, not the location.
- An address is a way of identifying a location in C's model, not a promise about hardware.
8. Exercise
Exercise 1 — read the picture. Using the memory strip in §2: what is count's address, how many bytes does it occupy, and what are the addresses of all the bytes belonging to it?
Exercise 2 — extend the picture. A second int object is placed immediately after count in the strip, on a system where an int occupies four bytes. What address does it start at, and which bytes does it own? Now answer the same question for a system where an int occupies two bytes.
Exercise 3 — explain with the new vocabulary. Chapter 2.1 asked you to explain why limit kept the value 3. Answer it again in one sentence, this time using the words object, storage and address.
Exercise 4 — reject four claims. Each of these is wrong or overstated. Say what is wrong with each:
(a) "An int is four bytes."
(b) "An object's address is fixed, so I can write the number down and use it next time I run the program."
(c) "A variable's address is where it is in my computer's memory chips."
(d) "Two objects declared one after the other are always next to each other in memory."
Exercise 5 — look ahead. In Module 7 you will meet an object whose value is the address of another object. Using only this chapter, describe what such an object would have to hold and roughly how much storage it might need. You are not expected to get the details right — the point is whether the sentence makes sense to you.
9. Summary
- Memory is numbered storage. Each location has an address, and the machine can reach any location directly by it.
- A byte is the smallest separately numbered unit; an object occupies a run of consecutive bytes.
- An object's address is the number of its first byte — not a list, and not something you supply.
- Type decides how many bytes. That count is implementation-defined;
intis commonly four and is nowhere required to be. - Separate objects mean separate storage. That, and nothing more mysterious, is why copying a value does not link two names.
- Addresses are not yours to choose or predict. The guarantee is structural: consecutive bytes, starting at the address, for as long as the object exists.
- The model has edges. It is about C's view of storage, not about hardware, and later chapters extend it rather than correcting it.
You now have objects and the storage they sit in. What you do not yet have is any account of what happens when an object is brought into existence without a starting value — something every program so far has carefully avoided. The next chapter is about that moment, and the answer is less forgiving than most beginners expect.
Standards & specifications
- Governing standard
- ISO/IEC 9899 (the C language standard)(opens ISO/IEC (JTC 1/SC 22/WG 14) in a new tab)
Defines the C language itself — the type system, expression semantics, object model, storage duration and the behaviour categories a conforming implementation must honour. It is a FAMILY of editions (C89/C90, C99, C11, C17, C23) and this curriculum names the edition wherever a claim depends on one. It does not define any foreign-function interface to a hardware description language, and it does not define platform behaviour: what a memory-mapped access does on real silicon is the implementation's and the device's contract, not this standard's. Working drafts published by WG14 are freely available and are what most engineers read day to day; a draft is not the published standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the C Programming curriculum.
