Memory, Pointers, and File I/O
Master low-level memory control, pointer mechanics, and persistent storage.
Content
Pointers and Addresses
Versions:
Watch & Learn
AI-discovered learning video
Sign in to watch the learning video for this topic.
Pointers and Addresses — the Real Map of Memory (CS50)
You just learned about the stack vs the heap — nice, you’ve toured the memory neighborhoods. Now let’s zoom in on the street signs: addresses and the mail carriers called pointers. Think of this as learning to read a memory map so you don’t accidentally mail a sandwich to a freed block.
"This is the moment where the concept finally clicks."
What a pointer is (short and spicy)
- Address: the numeric location of a memory cell (an apartment number for your value).
- Pointer: a variable whose value is an address — i.e., it points to where the real value lives.
- Dereference: using
*to go into that apartment and get or set the value inside.
Why it matters: pointers let you manipulate data without copying it (huge for big structs/arrays), let functions change callers' variables, and are the backbone of dynamic memory and many C APIs (including file streams, linked lists, and system calls).
Quick nod to earlier topics: when you benchmark recursion or worry about space complexity, remember that passing big data by value copies memory. Using pointers reduces space usage but keeps you responsible for memory hygiene.
Syntax & first examples (C)
Basic pointer ops
int x = 42; // a normal int on the stack (usually)
int *p = &x; // p stores the address of x
printf("x = %d, *p = %d\n", x, *p); // both print 42
printf("address: %p\n", (void*) p); // prints the pointer (address)
Micro explanation:
&x= "address of x"int *p= "p is a pointer to an int"*p= "the int that p points to"
Printing pointers
Always cast to (void*) when printing with %p to be portable.
Pointer arithmetic and arrays
Arrays and pointers are best friends (and emotionally codependent):
- The name of an array (e.g.,
arr) decays to a pointer to its first element in most expressions. p + 1moves to the next element of the typeppoints to — not the next byte.
Example:
int arr[3] = {10, 20, 30};
int *q = arr; // same as &arr[0]
// q points to 10. q+1 points to 20 (sizeof(int) bytes ahead)
printf("%d %d %d\n", q[0], *(q+1), *(q+2));
Micro explanation: pointer arithmetic scales by the size of the pointed-to type.
Passing pointers to functions — the swap classic
If you want a function to modify a variable from its caller, give it a pointer.
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
// Usage:
int m = 1, n = 2;
swap(&m, &n); // pass addresses
// now m == 2, n == 1
Why this matters for CS50 tasks: instead of copying a whole array into a function, pass a pointer and the length to keep time and space cost low (see your recursion & benchmarking notes).
Dynamic memory and ownership (heap reminders)
You saw stack vs heap earlier — pointers are how you get to heap allocations.
int *heap_arr = malloc(10 * sizeof(int));
if (heap_arr == NULL) exit(1);
heap_arr[0] = 7;
// ...
free(heap_arr);
heap_arr = NULL; // avoid dangling pointer
Rules of thumb:
- If you
malloc, you mustfree(or leak memory). - After
free, set pointer toNULLto avoid accidentally using a dangling pointer. - Don’t return pointers to local (stack) variables — that returns an address that vanishes when the function ends.
Safety checklist (because C will bite you)
- Check pointers for
NULLbefore dereferencing. - Avoid using freed (dangling) pointers.
- Be careful with pointer casts — they can break alignment and type safety.
- Prefer
constwhen you mean “don’t modify through this pointer”:const char *s.
Example: don't do this!
int *bad() {
int local = 5;
return &local; // local lives on the stack — invalid after return
}
A couple of useful pointer shapes
- Pointer to pointer (
int **pp) — used when you need to modify a pointer in the caller (or for dynamic 2D arrays). FILE *— used by file I/O functions likefopen,fread,fwrite. It’s a pointer to a struct that the C library manages.
Example opening a file:
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) { perror("fopen"); return 1; }
// use fp with fgets/fscanf/fread...
fclose(fp);
Note: FILE * is a pointer you must close with fclose to release OS-level resources.
Common confusions (and how to fix them)
- "A pointer points to the value" → No. A pointer stores an address that locates the value.
- "Array and pointer are identical" → Not exactly. Arrays decay to pointers in many contexts, but arrays allocate storage, pointers are variables that hold addresses.
- "Pointers to pointers are too far" → They are just addresses of variables that themselves are addresses. Practice with small diagrams and it becomes natural.
Imagine: a pointer is a little robot that carries the location of a book. Dereferencing makes the robot open the book and read or edit a page. If you tell the robot to go somewhere freed, it returns to an empty lot — not good.
Quick practice (do these in your CS50 sandbox)
- Write
swapusing pointers. - Write a function
reverse(char *s)that reverses a string in place using two pointers. - Allocate a 2D matrix with
mallocand free it. Use pointer-to-pointer or a flattened 1D buffer and pointer arithmetic.
These drill both pointer syntax and memory ownership rules.
Key takeaways
- Pointer = variable that stores an address. Dereference to get the value.
- Use pointers to avoid expensive copies (important for algorithmic space efficiency you’ve been studying).
- Be rigorous about ownership: who
mallocs and whofrees. Avoid dangling pointers and double-free. - When debugging: print pointer values (
%p) and validateNULLchecks.
Pointers feel scary at first because they give you power and responsibility. But once you can draw the memory map and follow the arrows, they unlock everything from efficient code to linked structures and low-level file I/O.
Go write some tiny pointer programs — it's where the learning sticks.
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!