Day 8: Pointers#

Overview#

Pointers are one of the most powerful and important features of C. A pointer is a variable that stores the memory address of another variable. Today we’ll demystify pointers and learn how to use them effectively.

What We’ll Learn Today#

  • What are pointers and why they matter
  • Address-of operator (&)
  • Dereference operator (*)
  • Declaring and using pointers
  • Pointer arithmetic
  • Pointers and arrays
  • Passing by reference

Understanding Memory#

Every variable in C occupies memory at a specific address:

int x = 42;
// x is stored at some memory location, say 0x7fff5fbff8c

The Address-of Operator (&)#

Gets the memory address of a variable:

#include <stdio.h>

int main() {
    int x = 42;

    printf("Value of x: %d\n", x);        // 42
    printf("Address of x: %p\n", &x);    // 0x7fff5fbff8c (varies)

    return 0;
}

Note: %p prints addresses in hexadecimal format.


What are Pointers?#

A pointer is a variable that stores a memory address:

int* ptr;  // Declare a pointer to an int

The Dereference Operator (*)#

Accesses the value at the address the pointer points to:

int x = 42;
int* ptr = &x;  // ptr now points to x

printf("Value at pointer: %d\n", *ptr);  // 42

Complete Pointer Example#

#include <stdio.h>

int main() {
    int x = 42;           // Variable
    int* ptr = &x;        // Pointer to x

    printf("x = %d\n", x);              // 42
    printf("Address of x: %p\n", &x);   // 0x...
    printf("ptr stores: %p\n", ptr);    // 0x... (same as &x)
    printf("Value at ptr: %d\n", *ptr); // 42

    // Modify through pointer
    *ptr = 100;
    printf("x is now: %d\n", x);        // 100

    return 0;
}

Output:

x = 42
Address of x: 0x7fff5fbff8c
ptr stores: 0x7fff5fbff8c
Value at ptr: 42
x is now: 100

Pointer Syntax#

int x = 5;
int* ptr = &x;  // Read: "ptr is a pointer to int, pointing to x"

// Access value: *ptr (dereference)
printf("%d\n", *ptr);   // 5

// Access address: ptr
printf("%p\n", ptr);    // 0x...

Common Confusion: * in Two Contexts#

// Declaration: * means "pointer to"
int* ptr;           // ptr is a pointer to int

// Dereference: * means "value at"
int value = *ptr;   // Get value at ptr

// Don't confuse these!
int* ptr1 = &x;     // ptr1 points to x
int  val  = *ptr1;  // val is the value x points to

Pointer Arithmetic#

Incrementing Pointers#

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr;  // Point to first element

    printf("First element: %d\n", *ptr);      // 10

    ptr++;           // Move to next element
    printf("Next element: %d\n", *ptr);       // 20

    ptr += 2;        // Move 2 positions forward
    printf("After +2: %d\n", *ptr);           // 40

    return 0;
}

Important: When you increment a pointer, it moves by the size of the data type:

  • int* ptr++ moves 4 bytes (size of int)
  • char* ptr++ moves 1 byte (size of char)

Pointer Subtraction#

int arr[] = {10, 20, 30, 40, 50};
int* ptr1 = &arr[0];
int* ptr2 = &arr[4];

int diff = ptr2 - ptr1;  // 4 (four elements apart)
printf("%d\n", diff);    // 4

Pointers and Arrays#

Arrays and pointers are closely related. The array name is a pointer to the first element:

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};

    printf("arr[0] = %d\n", arr[0]);       // 10
    printf("*arr = %d\n", *arr);           // 10 (same thing)

    printf("arr[2] = %d\n", arr[2]);       // 30
    printf("*(arr + 2) = %d\n", *(arr + 2)); // 30 (same thing)

    return 0;
}

Iterating with Pointers#

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr;

    // Print each element
    for (int i = 0; i < 5; i++) {
        printf("%d ", *ptr);
        ptr++;
    }
    printf("\n");  // Output: 10 20 30 40 50

    return 0;
}

Pointers to Different Data Types#

// Pointer to int
int x = 42;
int* ptr_int = &x;

// Pointer to float
float price = 19.99;
float* ptr_float = &price;

// Pointer to char
char grade = 'A';
char* ptr_char = &grade;

// Pointer to array
int arr[5] = {1, 2, 3, 4, 5};
int* ptr_arr = arr;

Pass by Reference Using Pointers#

Recall that functions pass by value. Using pointers, we can modify the original variable:

Without Pointers (Pass by Value)#

void increment(int num) {
    num++;  // Only increments the copy
}

int x = 5;
increment(x);
printf("%d\n", x);  // Still 5

With Pointers (Pass by Reference)#

void increment(int* num) {
    (*num)++;  // Increment the original
}

int x = 5;
increment(&x);
printf("%d\n", x);  // Now 6

Practical Example: Swap Function#

#include <stdio.h>

void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 10, y = 20;

    printf("Before: x = %d, y = %d\n", x, y);  // 10, 20

    swap(&x, &y);

    printf("After: x = %d, y = %d\n", x, y);   // 20, 10

    return 0;
}

Null Pointers#

A pointer that doesn’t point to anything should be set to NULL:

#include <stdio.h>

int main() {
    int* ptr = NULL;  // Null pointer (not pointing to anything)

    // Always check before using
    if (ptr != NULL) {
        printf("%d\n", *ptr);
    } else {
        printf("Pointer is NULL\n");
    }

    return 0;
}

Common Pointer Errors#

Error 1: Using Uninitialized Pointer#

// ❌ Wrong - ptr points to garbage memory
int* ptr;
printf("%d\n", *ptr);  // Crash!

// ✅ Correct
int x = 42;
int* ptr = &x;
printf("%d\n", *ptr);

Error 2: Forgetting & When Getting Address#

int x = 42;
int* ptr;

ptr = x;      // ❌ Wrong - assigns value, not address
ptr = &x;     // ✅ Correct - assigns address

Error 3: Forgetting * When Using Value#

int x = 42;
int* ptr = &x;

printf("%d\n", ptr);   // ❌ Wrong - prints address
printf("%d\n", *ptr);  // ✅ Correct - prints value

Practical Example: Array Operations with Pointers#

#include <stdio.h>

void printArray(int* arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", *(arr + i));
    }
    printf("\n");
}

int findMax(int* arr, int size) {
    int max = *arr;
    for (int i = 1; i < size; i++) {
        if (*(arr + i) > max) {
            max = *(arr + i);
        }
    }
    return max;
}

int main() {
    int scores[] = {85, 92, 78, 95, 88};
    int size = 5;

    printf("Scores: ");
    printArray(scores, size);

    printf("Maximum: %d\n", findMax(scores, size));

    return 0;
}

Output:

Scores: 85 92 78 95 88
Maximum: 95

Pointer Visualization#

Memory Layout:
┌─────────────────────────────┐
│ Address   │ Variable │ Value │
├─────────────────────────────┤
│ 0x1000    │ x        │ 42    │
│ 0x1004    │ ptr      │ 0x1000│
└─────────────────────────────┘

int x = 42;
int* ptr = &x;

x stores value 42 at address 0x1000
ptr stores address 0x1000 (where x is)

Practice Exercises#

Exercise 1: Pointer Basics#

Write a program that:

  • Creates an integer variable
  • Creates a pointer to it
  • Prints both value and address
  • Modifies through pointer

Exercise 2: Array with Pointers#

Write functions using pointers to:

  • Print array elements
  • Find sum of array
  • Find average of array

Exercise 3: Multiple Variable Swap#

Write a program that:

  • Takes 3 numbers
  • Swaps them using pointers
  • Displays before and after

Summary#

✅ Understood memory addresses
✅ Learned address-of (&) operator
✅ Learned dereference (*) operator
✅ Declared and used pointers
✅ Performed pointer arithmetic
✅ Worked with pointers and arrays
✅ Implemented pass by reference
✅ Avoided common pointer errors

Key Points to Remember#

  1. &x = address of x
  2. *ptr = value at address ptr points to
  3. int* ptr = &x creates pointer to int x
  4. Pointer arithmetic moves by data type size
  5. Always initialize pointers (or set to NULL)
  6. Check for NULL before dereferencing
  7. scanf("%d", &var) uses & to get address

Next Steps#

Tomorrow we’ll learn about structures and unions - how to group related data together!

→ Continue to Day 9

← Back to Day 7