DEV Community

Cover image for Pointers in C — Complete Guide
Farhad Rahimi Klie
Farhad Rahimi Klie

Posted on

Pointers in C — Complete Guide

Pointers are one of the most powerful and fundamental features in the C programming language. If you truly understand pointers, you unlock low-level memory control, efficient data structures, and system-level programming.


1. What is a Pointer?

A pointer is a variable that stores the memory address of another variable.

int a = 10;
int *p = &a;
Enter fullscreen mode Exit fullscreen mode

Memory Diagram

Stack Memory:

+------------+        +------------+
| a = 10     | 0x100  | p = 0x100  | 0x200
+------------+        +------------+

p ───────────────► a
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

  • ❌ Bug: printing pointer incorrectly
printf("%d", p); // WRONG
Enter fullscreen mode Exit fullscreen mode
  • ✅ Fix:
printf("%p", (void*)p);
Enter fullscreen mode Exit fullscreen mode

2. Pointer Declaration

data_type *pointer_name;
Enter fullscreen mode Exit fullscreen mode

Memory Insight

The pointer size is fixed (typically 4 or 8 bytes), regardless of type.

int *p;   // 8 bytes (on 64-bit system)
char *c;  // 8 bytes
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

  • ❌ Misinterpretation bug
char *p;
int x = 1000;
p = (char*)&x;
printf("%d", *p); // unexpected value
Enter fullscreen mode Exit fullscreen mode

3. Address Operator (&)

int x = 5;
printf("%p", &x);
Enter fullscreen mode Exit fullscreen mode

Memory Diagram

+------------+
| x = 5      | 0x300
+------------+

&x = 0x300
Enter fullscreen mode Exit fullscreen mode

4. Dereference Operator (*)

int x = 5;
int *p = &x;
printf("%d", *p);
Enter fullscreen mode Exit fullscreen mode

Memory Flow

p (0x400) ───► 0x300 ───► value 5
Enter fullscreen mode Exit fullscreen mode

Debug Scenario (Segmentation Fault)

int *p = NULL;
printf("%d", *p); // CRASH
Enter fullscreen mode Exit fullscreen mode

✔ Cause: dereferencing NULL


5. Pointer Initialization

Memory Risk

int *p;  // contains garbage address like 0xDEADBEEF
Enter fullscreen mode Exit fullscreen mode

Debug Scenario (Crash)

int *p;
*p = 10; // undefined behavior
Enter fullscreen mode Exit fullscreen mode

✔ Fix:

int *p = NULL;
Enter fullscreen mode Exit fullscreen mode

6. NULL Pointer

int *p = NULL;
Enter fullscreen mode Exit fullscreen mode

Memory Representation

p = 0x0
Enter fullscreen mode Exit fullscreen mode

Safe Usage Pattern

if (p != NULL) {
    *p = 10;
}
Enter fullscreen mode Exit fullscreen mode

7. Pointer Arithmetic

int arr[3] = {10, 20, 30};
int *p = arr;
p++;
Enter fullscreen mode Exit fullscreen mode

Memory Diagram

Address:   0x100   0x104   0x108
Values:    10      20      30
             ▲
             p (after p++)
Enter fullscreen mode Exit fullscreen mode

Debug Scenario (Out of Bounds)

int arr[3] = {1,2,3};
int *p = arr;
p += 5;
printf("%d", *p); // undefined
Enter fullscreen mode Exit fullscreen mode

8. Pointers and Arrays

int arr[3] = {1,2,3};
int *p = arr;
Enter fullscreen mode Exit fullscreen mode

Internal Model

arr == &arr[0]
Enter fullscreen mode Exit fullscreen mode
p + 1 == &arr[1]
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

printf("%lu", sizeof(arr)); // 12
printf("%lu", sizeof(p));   // 8
Enter fullscreen mode Exit fullscreen mode

✔ Arrays ≠ pointers


9. Pointer to Pointer

int x = 5;
int *p = &x;
int **pp = &p;
Enter fullscreen mode Exit fullscreen mode

Memory Diagram

pp ──► p ──► x
Enter fullscreen mode Exit fullscreen mode
0x500  0x400  0x300
Enter fullscreen mode Exit fullscreen mode

10. Function Pointers

int add(int a, int b) { return a + b; }
int (*fp)(int,int) = add;
Enter fullscreen mode Exit fullscreen mode

Memory Model

Code Segment:
add() at 0x900

Stack:
fp = 0x900
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

int (*fp)(int,int);
fp(2,3); // crash
Enter fullscreen mode Exit fullscreen mode

✔ Fix: initialize before use


11. Dynamic Memory Allocation

int *p = malloc(sizeof(int));
*p = 10;
free(p);
Enter fullscreen mode Exit fullscreen mode

Memory Diagram

Heap:
0xA00 → [10]

Stack:
p = 0xA00
Enter fullscreen mode Exit fullscreen mode

Debug Scenario (Memory Leak)

int *p = malloc(sizeof(int));
p = NULL; // lost reference
Enter fullscreen mode Exit fullscreen mode

✔ Leak: memory still allocated


12. Void Pointer

void *p;
Enter fullscreen mode Exit fullscreen mode

Rule

Cannot dereference without casting

int x = 5;
p = &x;
printf("%d", *(int*)p);
Enter fullscreen mode Exit fullscreen mode

13. Dangling Pointer

int *p = malloc(sizeof(int));
free(p);
Enter fullscreen mode Exit fullscreen mode

Memory Diagram

p ──► freed memory (invalid)
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

*p = 20; // undefined behavior
Enter fullscreen mode Exit fullscreen mode

✔ Fix:

free(p);
p = NULL;
Enter fullscreen mode Exit fullscreen mode

14. Wild Pointer

int *p;
Enter fullscreen mode Exit fullscreen mode

Memory

p = random address
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

*p = 10; // crash
Enter fullscreen mode Exit fullscreen mode

15. Const Pointer

const int *p;
int *const p;
Enter fullscreen mode Exit fullscreen mode

Memory Behavior

  • const int *p → value locked
  • int *const p → address locked

16. Pointer and Strings

char *str = "Hello";
Enter fullscreen mode Exit fullscreen mode

Memory Layout

Code Segment:
"Hello" (read-only)

Stack:
str → address of string
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

str[0] = 'h'; // crash (read-only memory)
Enter fullscreen mode Exit fullscreen mode

17. Pointers vs Arrays

Deep Difference

int arr[3]; // fixed memory
int *p;     // dynamic reference
Enter fullscreen mode Exit fullscreen mode

Debug Scenario

arr = p; // ❌ illegal
Enter fullscreen mode Exit fullscreen mode

18. Memory Layout (Deep View)

+-------------------+
| Code Segment      |
+-------------------+
| Global/Static     |
+-------------------+
| Stack             |
|  - local vars     |
+-------------------+
| Heap              |
|  - malloc memory  |
+-------------------+
Enter fullscreen mode Exit fullscreen mode

Debug Scenario (Stack Overflow)

void func() {
    int arr[1000000];
}
Enter fullscreen mode Exit fullscreen mode

19. Common Mistakes (With Debug Insight)

  • Uninitialized pointer → crash
  • Double free → heap corruption
  • Memory leak → performance issue
  • Out-of-bounds → undefined behavior

20. Best Practices (Professional Level)

  • Always initialize pointers
  • Use NULL after free
  • Use tools like:

    • valgrind
    • address sanitizer

🚀 5 Practical Projects Using Pointers (Advanced Level)

1. Dynamic Array (Vector)

Add:

  • resizing logic
  • capacity vs size tracking

2. Linked List (Singly)

Add:

  • insert/delete at position
  • reverse list (pointer manipulation heavy)

3. String Library (Pointer-only)

Implement using only pointers (no indexing)


4. Custom Memory Allocator

Simulate heap blocks:

[metadata][data][metadata][data]
Enter fullscreen mode Exit fullscreen mode

5. Callback/Event System

Simulate event handlers using function pointers


Conclusion

Pointers are not just a feature — they are the core of C programming.

With memory diagrams + debugging understanding, you now think like a systems programmer.

Top comments (0)