Phase 4 — Pointers & Memory ⭐
This is the most important low-level phase in C.
The central idea is:
A normal variable stores a value. A pointer stores an address where a value lives.
Once this becomes natural, arrays, strings, dynamic memory, structures, linked lists, callbacks, and much of systems programming become significantly easier.
Module 1 — Understanding Addresses & Pointers
Chapter 1 — Memory Addresses
Question
Given below is a program that creates two integer variables and prints their values and addresses.
What should the output look like?
#include <stdio.h>
int main(void)
{
int age = 35;
int score = 90;
// Print the values stored in the variables.
printf("age = %d\n", age);
printf("score = %d\n", score);
// Print the memory addresses of the variables.
printf("&age = %p\n", (void *)&age);
printf("&score = %p\n", (void *)&score);
return 0;
}Answer
age = 35
score = 90
&age = 0x........
&score = 0x........The exact addresses cannot be predicted.
Step-by-step explanation
agestores35.scorestores90.&agemeans "address of age."&scoremeans "address of score."%pis used to print an address.The
(void *)cast is the conventional form for passing a pointer toprintf("%p").
Think of memory like houses:
Memory
Address Value
1000 35 ← age
1004 90 ← scoreThe address is where the value lives.
How to read the important code
&ageRead naturally as:
"the address of age"
%pRead as:
"print a pointer/address"
Key takeaway
&variablegives you the variable's memory address.
Chapter 2 — What Is a Pointer?
Question
What will this print?
#include <stdio.h>
int main(void)
{
int age = 35;
// p stores the address of age.
int *p = &age;
printf("%d\n", age);
printf("%d\n", *p);
return 0;
}Answer
35
35Step-by-step explanation
This line:
int *p = &age;means:
Create a pointer named
pthat can point to anint, and store the address ofageinside it.
Imagine:
age
┌───────┐
│ 35 │
└───────┘
↑
│
pp contains the address.
Then:
*pmeans:
Go to the address stored inside
pand access the value there.
Therefore:
ageand
*pboth produce 35.
Key takeaway
pis the address;*paccesses the value at that address.
Chapter 3 — Dereferencing a Pointer
Question
What will the final value of x be?
#include <stdio.h>
int main(void)
{
int x = 10;
// p points to x.
int *p = &x;
// Change x through its pointer.
*p = 50;
printf("%d\n", x);
return 0;
}Answer
50Step-by-step explanation
Initially:
x = 10Then:
p = &x;Now p points to x.
Then:
*p = 50;means:
Go to the memory location represented by
pand put50there.
So:
Before:
x → 10
After:
x → 50Key takeaway
Dereferencing lets a pointer modify the object it points to.
Chapter 4 — Pointer Types
Question
What does this program print?
#include <stdio.h>
int main(void)
{
int x = 100;
double y = 3.14;
// Each pointer is designed for a particular type.
int *ip = &x;
double *dp = &y;
printf("%d\n", *ip);
printf("%.2f\n", *dp);
return 0;
}Answer
100
3.14Step-by-step explanation
These are different pointer types:
int *ip;
double *dp;ip is an int *.
dp is a double *.
The type matters because C needs to know how to interpret the memory and how pointer arithmetic should behave.
For example:
int *p;means:
ppoints to anint.
Key takeaway
A pointer has a type describing the kind of object it points to.
Module 2 — Pointers and Arrays
Chapter 5 — Arrays and Addresses
Question
What will this print?
#include <stdio.h>
int main(void)
{
int numbers[] = {10, 20, 30};
// The array name represents the address of its first element
// in this expression.
int *p = numbers;
printf("%d\n", *p);
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 2));
return 0;
}Answer
10
20
30Step-by-step explanation
The array is conceptually:
numbers
┌────┬────┬────┐
│ 10 │ 20 │ 30 │
└────┴────┴────┘
↑
pp points to the first element.
So:
*p→ 10
*(p + 1)→ 20
*(p + 2)→ 30
Important:
p + 1 does not necessarily mean one byte forward.
For an int *, it means:
Move forward by one
int.
Key takeaway
Pointer arithmetic moves according to the size of the pointed-to type.
Chapter 6 — Pointer Arithmetic
Question
Assume sizeof(int) == 4.
What values are printed?
#include <stdio.h>
int main(void)
{
int numbers[] = {10, 20, 30};
int *p = numbers;
printf("%d\n", *p);
p++;
printf("%d\n", *p);
p++;
printf("%d\n", *p);
return 0;
}Answer
10
20
30Step-by-step explanation
Initially:
p → numbers[0]After:
p++;p → numbers[1]After another:
p++;p → numbers[2]If an int occupies 4 bytes:
1000 → 10
1004 → 20
1008 → 30p++ moves from 1000 to 1004, not 1001.
Key takeaway
p + nmoves bynelements, notnbytes.
Chapter 7 — Arrays and Pointers Are Not the Same Thing
Question
Which statements are true?
#include <stdio.h>
int main(void)
{
int a[] = {10, 20, 30};
int *p = a;
printf("%zu\n", sizeof(a));
printf("%zu\n", sizeof(p));
return 0;
}Answer
sizeof(a) gives the size of the entire array.
sizeof(p) gives the size of the pointer itself.
For example, on a common 64-bit system:
sizeof(a) → 12
sizeof(p) → 8assuming sizeof(int) == 4.
Step-by-step explanation
An array:
int a[3];actually contains three int objects.
A pointer:
int *p;contains an address.
Therefore:
array → actual elements
pointer → addressThey are closely related, but they are not the same type.
Key takeaway
An array is storage for elements; a pointer is an object containing an address.
Module 3 — Pointers and Functions
Chapter 8 — Passing a Pointer to a Function
Question
What is printed?
#include <stdio.h>
void change(int *p)
{
// Modify the caller's variable.
*p = 99;
}
int main(void)
{
int x = 10;
change(&x);
printf("%d\n", x);
return 0;
}Answer
99Step-by-step explanation
The call:
change(&x);passes the address of x.
Inside:
void change(int *p)p receives that address.
Then:
*p = 99;changes the original x.
This is one of the most important uses of pointers.
Java comparison
Java also passes arguments by value, but object references make the behavior look different.
C gives you explicit control over the address.
Key takeaway
Passing an address allows a function to modify the caller's object.
Chapter 9 — C Is Pass-by-Value
Question
Will x become 100?
#include <stdio.h>
void change(int x)
{
// This changes only the local copy.
x = 100;
}
int main(void)
{
int x = 10;
change(x);
printf("%d\n", x);
return 0;
}Answer
10Step-by-step explanation
C passes the argument by value.
So:
change(x);creates a copy.
Conceptually:
main's x → 10
function's x → 10
↓
100The function changes its own copy.
To modify the original, pass its address:
change(&x);Key takeaway
C does not have true pass-by-reference; pointers are used to achieve reference-like behavior.
Module 4 — NULL, Invalid & Dangerous Pointers
Chapter 10 — NULL Pointers
Question
What is safe about this code?
#include <stdio.h>
int main(void)
{
int *p = NULL;
if (p != NULL) {
printf("%d\n", *p);
}
return 0;
}Answer
The program does not dereference p.
Step-by-step explanation
NULL means:
This pointer currently does not point to a valid object.
This is dangerous:
*pwhen p == NULL.
Instead:
if (p != NULL)checks first.
Key takeaway
Never dereference a null pointer.
Chapter 11 — Wild Pointers
Question
Is this safe?
#include <stdio.h>
int main(void)
{
int *p;
*p = 10;
return 0;
}Answer
No.
p is uninitialized.
It contains an indeterminate value and does not point to a valid int object.
Dereferencing it produces undefined behavior.
Key takeaway
An uninitialized pointer is dangerous; initialize pointers deliberately.
Chapter 12 — Dangling Pointers
Question
What is wrong here?
#include <stdio.h>
int *get_pointer(void)
{
int x = 10;
// x stops existing when this function returns.
return &x;
}
int main(void)
{
int *p = get_pointer();
printf("%d\n", *p);
return 0;
}Answer
p becomes a dangling pointer.
Step-by-step explanation
Inside get_pointer():
int x = 10;x is a local variable.
When the function returns:
x's lifetime endsBut the returned address still exists inside p.
So:
p → dead objectDereferencing it is undefined behavior.
Key takeaway
Never return a pointer to a local automatic variable.
Module 5 — Pointers to Structures
Chapter 13 — -> Operator
Question
What is printed?
#include <stdio.h>
struct Person {
int age;
};
int main(void)
{
struct Person person = {35};
// Point to the structure.
struct Person *p = &person;
// Access the member through the pointer.
p->age = 36;
printf("%d\n", person.age);
return 0;
}Answer
36Step-by-step explanation
Without a pointer:
person.ageWith a pointer:
p->ageThese are equivalent:
p->ageand:
(*p).ageThe arrow is simply the convenient syntax.
Key takeaway
p->membermeans "access this structure member through pointerp."
Module 6 — Pointer to Pointer
Chapter 14 — **
Question
What is printed?
#include <stdio.h>
int main(void)
{
int x = 10;
// p points to x.
int *p = &x;
// pp points to p.
int **pp = &p;
**pp = 50;
printf("%d\n", x);
return 0;
}Answer
50Step-by-step explanation
We have three levels:
x
↑
p
↑
ppMore precisely:
pp
↓
p
↓
xTherefore:
*ppgives p.
And:
**ppgives x.
So:
**pp = 50;changes x.
Key takeaway
int **is a pointer to anint *.
Module 7 — void *, Arrays of Pointers & Function Pointers
Chapter 15 — void *
Question
What happens here?
#include <stdio.h>
int main(void)
{
int x = 42;
// Generic object pointer.
void *p = &x;
// Convert back to int pointer before dereferencing.
printf("%d\n", *(int *)p);
return 0;
}Answer
42Step-by-step explanation
void * can hold the address of an object of essentially any object type.
But C does not know what type the pointed-to object is.
Therefore this is not generally valid:
*pInstead, convert it to the appropriate pointer type:
*(int *)pKey takeaway
void *is a generic object pointer, but you need the correct type before dereferencing it.
Chapter 16 — Arrays of Pointers
Question
What is printed?
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 20;
// Each element stores an address.
int *ptrs[] = {&a, &b};
printf("%d\n", *ptrs[0]);
printf("%d\n", *ptrs[1]);
return 0;
}Answer
10
20Step-by-step explanation
This:
int *ptrs[2];means:
An array containing two pointers to
int.
Conceptually:
ptrs[0] → a → 10
ptrs[1] → b → 20Key takeaway
int *p[3]means "array of 3 pointers to int."
Chapter 17 — Function Pointers
Question
What is printed?
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int main(void)
{
// fp points to a function taking two ints and returning int.
int (*fp)(int, int) = add;
printf("%d\n", fp(10, 20));
return 0;
}Answer
30Step-by-step explanation
Functions also have addresses.
This declaration:
int (*fp)(int, int);means:
fpis a pointer to a function that takes twointarguments and returns anint.
Then:
fp = add;makes it point to add.
Therefore:
fp(10, 20)calls add.
Function pointers become important for:
callbacks
event systems
sorting
APIs
state machines
operating-system interfaces
Key takeaway
A function pointer stores the address of a function and can be used to call it.
Module 8 — Dynamic Memory ⭐
Now we move from pointers to heap memory.
The key distinction:
Stack
─────
automatic/local objects
Heap
────
dynamically allocated memoryChapter 18 — malloc
Question
What does this program print?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Allocate space for one int on the heap.
int *p = malloc(sizeof *p);
// Always check whether allocation succeeded.
if (p == NULL) {
return 1;
}
*p = 42;
printf("%d\n", *p);
// Release the allocated memory.
free(p);
return 0;
}Answer
42Step-by-step explanation
malloc(sizeof *p)requests enough heap memory for one int.
If successful:
p
↓
┌──────┐
│ 42 │
└──────┘
heapThen:
free(p);returns that memory to the allocator.
Important pattern
int *p = malloc(sizeof *p);
if (p == NULL) {
// allocation failed
}Then eventually:
free(p);Key takeaway
mallocallocates heap memory;freereleases it.
Chapter 19 — calloc
Question
What will this print?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Allocate space for 3 ints and initialize all bytes to zero.
int *numbers = calloc(3, sizeof *numbers);
if (numbers == NULL) {
return 1;
}
printf("%d %d %d\n",
numbers[0],
numbers[1],
numbers[2]);
free(numbers);
return 0;
}Answer
0 0 0Step-by-step explanation
calloc allocates:
3 × sizeof(int)bytes and initializes the allocated bytes to zero.
For ordinary integer objects, this results in zero values.
Key takeaway
calloc(n, size)allocates space fornobjects and zero-initializes the allocated bytes.
Chapter 20 — realloc
Question
What is the purpose of realloc here?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *numbers = malloc(2 * sizeof *numbers);
if (numbers == NULL) {
return 1;
}
numbers[0] = 10;
numbers[1] = 20;
// Request space for 4 ints.
int *tmp = realloc(numbers, 4 * sizeof *numbers);
if (tmp == NULL) {
// Original allocation is still valid here.
free(numbers);
return 1;
}
numbers = tmp;
numbers[2] = 30;
numbers[3] = 40;
printf("%d %d %d %d\n",
numbers[0],
numbers[1],
numbers[2],
numbers[3]);
free(numbers);
return 0;
}Answer
10 20 30 40Step-by-step explanation
Initially:
capacity = 2Then:
realloc(numbers, 4 * sizeof *numbers)requests enough space for four integers.
It may:
enlarge the existing allocation, or
allocate a new region and copy the old contents.
This is why using a temporary pointer is safer:
int *tmp = realloc(...);Do not blindly do:
numbers = realloc(numbers, ...);because if realloc fails, you could lose the original pointer.
Key takeaway
Use a temporary pointer when calling
realloc.
Chapter 21 — free
Question
What is wrong with this?
#include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof *p);
if (p == NULL) {
return 1;
}
*p = 10;
free(p);
printf("%d\n", *p);
return 0;
}Answer
The program accesses memory after it has been freed.
That is use-after-free and therefore undefined behavior.
After:
free(p);think:
p → no longer owns a valid allocated objectA useful practice is:
free(p);
p = NULL;when the pointer remains in scope and might otherwise accidentally be reused.
Key takeaway
After
free, the allocated object no longer exists.
Module 9 — Memory Bugs & Ownership
Chapter 22 — Memory Leak
Question
What is wrong here?
#include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof *p);
if (p == NULL) {
return 1;
}
*p = 100;
// Program loses the only pointer to the allocation.
p = NULL;
return 0;
}Answer
The allocated memory is leaked.
Step-by-step explanation
Initially:
p → heap allocationThen:
p = NULL;Now:
p → NULL
heap allocation → unreachableThere is no way to call:
free(...)on that allocation anymore.
Correct:
free(p);
p = NULL;Key takeaway
Every successful allocation needs a clear path to
free.
Chapter 23 — Double Free
Question
What is wrong?
#include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof *p);
if (p == NULL) {
return 1;
}
free(p);
free(p);
return 0;
}Answer
p is freed twice.
This is double free, which is undefined behavior.
Safer:
free(p);
p = NULL;Then:
free(p);is valid because free(NULL) is defined to do nothing.
Key takeaway
Free an allocation exactly once.
Chapter 24 — Ownership and Lifetime
Question
Who should free this memory?
int *create_number(void)
{
int *p = malloc(sizeof *p);
if (p != NULL) {
*p = 42;
}
return p;
}Answer
The caller that receives the returned pointer now needs to manage the allocation.
For example:
int *p = create_number();
if (p != NULL) {
printf("%d\n", *p);
free(p);
}Step-by-step explanation
A useful mental model is ownership.
create_number() creates the allocation.
The caller receives it:
create_number()
│
▼
heap
▲
│
callerThe caller should know:
"I received this allocated memory, so I am responsible for releasing it."
C does not automatically enforce ownership.
Key takeaway
In C, programmers must deliberately define who owns and frees dynamically allocated memory.
Module 10 — Complex Pointer Concepts
Chapter 25 — const With Pointers
Question
Which operations are allowed?
int x = 10;
int y = 20;
const int *p = &x;
// *p = 30; // ❌ not allowed through p
p = &y; // ✅ allowedAnswer
Here:
const int *p;means:
ppoints to anintthat cannot be modified through this pointer.
It does not mean the pointer itself cannot move.
Therefore:
p = &y;is allowed.
There are three important forms:
const int *p;Pointer to const int.
int *const p = &x;Const pointer to int.
const int *const p = &x;Const pointer to const int.
Key takeaway
With pointers, determine separately whether the pointed-to object or the pointer itself is const.
Chapter 26 — Pointer to Array
Question
What does this declaration mean?
int (*p)[3];Answer
It means:
pis a pointer to an array of 3 integers.
Compare:
int *p[3];which means:
pis an array of 3 pointers to integers.
Parentheses matter enormously.
int (*p)[3]
↑
pointer to array
int *p[3]
↑
array of pointersKey takeaway
In C declarations, parentheses can completely change what a pointer declaration means.
Chapter 27 — Pointer Casting
Question
What is happening here?
int x = 42;
void *p = &x;
int *ip = (int *)p;Answer
The address stored in p is being converted from:
void *to:
int *so it can be interpreted as pointing to an int.
However:
A cast does not magically make an invalid pointer valid.
The underlying address must actually be suitable for the target interpretation.
Key takeaway
Casting a pointer changes how C interprets the pointer; it does not repair invalid memory.
Module 11 — Undefined Behavior ⭐
Chapter 28 — What Is Undefined Behavior?
Question
What is wrong with this?
#include <stdio.h>
int main(void)
{
int numbers[3] = {10, 20, 30};
printf("%d\n", numbers[5]);
return 0;
}Answer
numbers[5] is outside the array.
The program has undefined behavior.
It might:
print a strange number
appear to work
crash
behave differently after optimization
produce completely unexpected results
The crucial point is:
C does not promise what will happen.
Key takeaway
Undefined behavior means you cannot safely reason from the program's expected result.
Chapter 29 — Out-of-Bounds Pointer Arithmetic
Question
Is this valid?
int numbers[3] = {10, 20, 30};
int *p = numbers;
p = p + 3;Answer
This is an important subtlety.
A pointer may legally point one past the end of an array:
numbers:
[10] [20] [30] [one-past]
↑
pSo:
p + 3can form the one-past pointer.
But this is not valid:
*pafter p has become one-past.
Key takeaway
One-past-the-end pointers may be formed and compared, but must not be dereferenced.
Module 12 — Memory Layout & Stack vs Heap
Chapter 30 — Stack vs Heap
Question
Where do these objects conceptually live?
#include <stdlib.h>
int main(void)
{
int x = 10;
int *p = malloc(sizeof *p);
if (p == NULL) {
return 1;
}
*p = 20;
free(p);
return 0;
}Answer
Conceptually:
Stack
──────────────
x
p
──────────────
Heap
──────────────
allocated int
──────────────x is an automatic local object.
The memory obtained by malloc is dynamically allocated storage.
Important distinction
Do not think:
"Every pointer is on the heap."
p itself is a local variable and commonly lives in the stack frame.
The object p points to is the dynamically allocated memory.
Key takeaway
A pointer and the object it points to are two separate objects with potentially different lifetimes and storage locations.
Chapter 31 — Stack Frames
Question
What happens conceptually when this executes?
int add(int a, int b)
{
int result = a + b;
return result;
}
int main(void)
{
int x = add(10, 20);
return 0;
}Answer
Conceptually, a call to add() creates a new execution context containing things such as:
add stack frame
──────────────
a
b
result
return information
──────────────Then the function returns.
Its local automatic objects cease to exist.
This explains why returning:
return &result;would be invalid.
Key takeaway
Local variables have lifetimes tied to their execution scope/storage duration.
Module 13 — Advanced Pointer Concepts
Chapter 32 — Callbacks
Question
What is printed?
#include <stdio.h>
int square(int x)
{
return x * x;
}
int apply(int value, int (*operation)(int))
{
// Call whichever function was supplied.
return operation(value);
}
int main(void)
{
printf("%d\n", apply(5, square));
return 0;
}Answer
25Step-by-step explanation
apply() receives a function pointer:
int (*operation)(int)Then:
operation(value)calls the supplied function.
So:
apply
↓
square
↓
25This is a callback pattern.
Key takeaway
Function pointers allow behavior to be passed into functions.
Chapter 33 — Pointer Aliasing
Question
What happens here?
int x = 10;
int *a = &x;
int *b = &x;
*a = 50;
printf("%d\n", *b);Answer
50Step-by-step explanation
Both pointers point to the same object:
┌──────┐
a ───►│ │
│ 10 │
b ───►│ │
└──────┘After:
*a = 50;the object becomes 50.
Therefore *b also sees 50.
This relationship is called aliasing.
Key takeaway
Multiple pointers can refer to the same object.
Chapter 34 — restrict
Question
What is the purpose of restrict here?
void add_arrays(
int *restrict out,
const int *restrict a,
const int *restrict b,
int n
)
{
for (int i = 0; i < n; i++) {
out[i] = a[i] + b[i];
}
}Answer
restrict tells the compiler that, under the programmer's contract, the objects accessed through these restricted pointers are not being accessed through competing pointer paths in a conflicting way.
This can enable optimization.
But it creates a programmer responsibility.
If you violate the restrictions, behavior can become undefined.
Key takeaway
restrictis an optimization-related promise about pointer aliasing, not a magical performance switch.
Module 14 — The Big Picture
Chapter 35 — Putting Pointers and Dynamic Memory Together
Question
What does this program ultimately print?
#include <stdio.h>
#include <stdlib.h>
void double_values(int *numbers, int count)
{
// Modify each heap element through the pointer.
for (int i = 0; i < count; i++) {
numbers[i] *= 2;
}
}
int main(void)
{
int count = 3;
// Allocate an array on the heap.
int *numbers = malloc(count * sizeof *numbers);
if (numbers == NULL) {
return 1;
}
// Initialize the dynamically allocated array.
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
// Pass the address of the first element.
double_values(numbers, count);
printf("%d %d %d\n",
numbers[0],
numbers[1],
numbers[2]);
// Release the heap allocation.
free(numbers);
return 0;
}Answer
20 40 60Step-by-step explanation
The important chain is:
malloc
↓
heap memory
↓
numbers
↓
pointer to first element
↓
double_values()
↓
numbers[i] *= 2
↓
same heap objects modified
↓
free()This one program combines:
pointers
arrays
pointer/function interaction
dynamic allocation
mallocNULL checking
dereferencing
pointer-based modification
ownership
free
Key takeaway
This is the fundamental C pattern: allocate memory → access it through pointers → modify it → release it.
Phase 4 — Master Mental Model
At the end of Phase 4, you should be able to look at C code and mentally translate it like this:
int x = 10;↓
Create an integer object containing 10.
int *p = &x;↓
Create a pointer containing x's address.
*p↓
Access the integer located at that address.
*p = 20;↓
Modify that integer.
int **pp = &p;↓
Create a pointer to the pointer.
malloc(...)↓
Ask the allocator for dynamic storage.
free(p);↓
Release the dynamic allocation owned through
p.
Phase 4 — The Pointer Map
Memorize this relationship:
ADDRESS
│
▼
┌───────────┐
│ p │
│ address │
└─────┬─────┘
│
*p
│
▼
┌───────────┐
│ x │
│ value │
└───────────┘And for pointer-to-pointer:
┌──────┐ ┌──────┐ ┌──────┐
│ pp │ ────► │ p │ ────► │ x │
│ │ │ │ │ 10 │
└──────┘ └──────┘ └──────┘
**pp = x
*pp = p
pp = address of pPhase 4 — What You Must Now Be Able to Recognize
You should now recognize these immediately:
| Code | Meaning |
|---|---|
&x | address of x |
int *p | pointer to int |
*p | value/object pointed to by p |
*p = 5 | modify pointed-to object |
p + 1 | next element for an appropriate array pointer |
p->x | structure member through pointer |
int **p | pointer to pointer to int |
void *p | generic object pointer |
malloc() | dynamically allocate memory |
calloc() | dynamically allocate zero-initialized bytes |
realloc() | resize an allocation |
free() | release dynamic allocation |
NULL | null pointer value |
| dangling pointer | pointer to an object whose lifetime ended |
| wild pointer | uninitialized/invalid pointer |
| memory leak | allocated memory no longer reachable for freeing |
| double free | same allocation released twice |
| use-after-free | accessing an object after it was freed |
| UB | undefined behavior |
The most important distinction
Never confuse these three:
p → the pointer/address
*p → the object/value at that address
&p → the address of the pointer itselfFor:
int x = 10;
int *p = &x;you have:
x = 10
p = address of x
*p = 10
&x = address of x
&p = address of pThat distinction is the core of C pointers.
Phase 4 Complete
You have now covered the full Phase 4 scope:
addresses → pointers → dereferencing → pointer types → arrays → pointer arithmetic → strings → function pointers → callbacks → ** → void * → NULL/wild/dangling pointers → structures → -> → stack/heap → malloc → calloc → realloc → free → ownership/lifetime → memory leaks → double free → use-after-free → complex declarations → const pointers → casts → aliasing → restrict → undefined behavior → memory layout.
Phase 5 is not started.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.