Lecture 18: Pointers in C

Unit IV: Structures and Pointers

Dr. Mohsin Dar

Assistant Professor, Cloud & Software Operations Cluster | SOCS | UPES

Topics Covered Today

  • Introduction to Pointers
  • Declaring and Initializing Pointers
  • Dereferencing Pointers
  • Size of Pointers
  • Special Types of Pointers
  • Pointer Arithmetic
  • Multilevel Pointers
  • Practice Problems

What are Pointers?

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

Pointers are one of the most powerful features in C programming, allowing direct memory manipulation.

Why Use Pointers?

  • Dynamic memory allocation
  • Efficient array and string handling
  • Pass by reference in functions
  • Implement complex data structures (linked lists, trees, etc.)
  • Direct hardware manipulation

Memory Address Concept

Variable: x Value: 10 Address: 0x1000
Pointer: ptr Value: 0x1000 Address: 0x2000

Declaring a Pointer

Syntax

data_type *pointer_name;

The asterisk (*) is used to declare a pointer variable.

Examples

int *ptr; // Pointer to an integer float *fptr; // Pointer to a float char *cptr; // Pointer to a character double *dptr; // Pointer to a double
Note: When a pointer is declared, it contains garbage value. It must be initialized before use.

Complete Example

#include <stdio.h> int main() { int *ptr; // Declaration of integer pointer char *cptr; // Declaration of character pointer printf("Pointers declared successfully!\n"); return 0; }

Initialize the Pointer

Address-of Operator (&)

The & operator returns the memory address of a variable.

int x = 10; int *ptr = &x; // ptr now stores the address of x

Complete Example

#include <stdio.h> int main() { int num = 42; int *ptr = # // Initialize pointer with address of num printf("Value of num: %d\n", num); printf("Address of num: %p\n", &num); printf("Value stored in ptr: %p\n", ptr); printf("Address of ptr: %p\n", &ptr); return 0; }

Memory Visualization

num Value: 42 Address: 0x7ffe5c
ptr Value: 0x7ffe5c Address: 0x7ffe60

Dereference a Pointer

Dereference Operator (*)

The * operator (when used with a pointer) accesses the value stored at the address the pointer points to.

Example

#include <stdio.h> int main() { int x = 25; int *ptr = &x; printf("Value of x: %d\n", x); printf("Value at address stored in ptr: %d\n", *ptr); // Modify value using pointer *ptr = 50; printf("New value of x: %d\n", x); printf("New value at *ptr: %d\n", *ptr); return 0; }

Output

Value of x: 25 Value at address stored in ptr: 25 New value of x: 50 New value at *ptr: 50
Key Point: Modifying *ptr modifies the original variable because they both refer to the same memory location.

Size of Pointers

The size of a pointer depends on the architecture of the system, not the data type it points to.

  • 32-bit system: Pointer size = 4 bytes
  • 64-bit system: Pointer size = 8 bytes

Example

#include <stdio.h> int main() { int *iptr; char *cptr; float *fptr; double *dptr; printf("Size of int pointer: %zu bytes\n", sizeof(iptr)); printf("Size of char pointer: %zu bytes\n", sizeof(cptr)); printf("Size of float pointer: %zu bytes\n", sizeof(fptr)); printf("Size of double pointer: %zu bytes\n", sizeof(dptr)); return 0; }

Output (on 64-bit system)

Size of int pointer: 8 bytes Size of char pointer: 8 bytes Size of float pointer: 8 bytes Size of double pointer: 8 bytes
Important: All pointers have the same size regardless of the data type they point to, because they all store memory addresses.

Special Types of Pointers (Part 1)

1. NULL Pointer

A pointer that points to nothing. It's initialized with NULL value.

#include <stdio.h> int main() { int *ptr = NULL; // NULL pointer initialization if (ptr == NULL) { printf("Pointer is NULL\n"); } // Always check before dereferencing if (ptr != NULL) { printf("Value: %d\n", *ptr); } else { printf("Cannot dereference NULL pointer\n"); } return 0; }

2. Void Pointer

A generic pointer that can point to any data type.

#include <stdio.h> int main() { void *ptr; int x = 10; float y = 5.5; ptr = &x; printf("Integer: %d\n", *(int*)ptr); ptr = &y; printf("Float: %.2f\n", *(float*)ptr); return 0; }
Note: Void pointers must be type-cast before dereferencing.

Special Types of Pointers (Part 2)

3. Wild Pointers

Pointers that are not initialized and contain garbage values.

#include <stdio.h> int main() { int *ptr; // Wild pointer - not initialized! // DANGER: This can cause undefined behavior // printf("%d\n", *ptr); // DON'T DO THIS! // Always initialize pointers ptr = NULL; // Now it's safe return 0; }
Warning: Never use wild pointers! Always initialize pointers before use.

4. Dangling Pointer

A pointer that points to freed or deallocated memory.

#include <stdio.h> #include <stdlib.h> int main() { int *ptr = (int*)malloc(sizeof(int)); *ptr = 100; printf("Value: %d\n", *ptr); free(ptr); // Memory deallocated // ptr is now a dangling pointer ptr = NULL; // Good practice: Set to NULL after free return 0; }
Warning: Always set pointers to NULL after freeing memory to avoid dangling pointer issues.

C Pointer Arithmetic

Operations Allowed

Pointers support the following arithmetic operations:

  • Increment: ptr++ or ++ptr
  • Decrement: ptr-- or --ptr
  • Addition: ptr + n
  • Subtraction: ptr - n
  • Difference: ptr1 - ptr2

Example 1: Array Traversal

#include <stdio.h> int main() { int arr[] = {10, 20, 30, 40, 50}; int *ptr = arr; // Points to first element printf("Array elements using pointer arithmetic:\n"); for (int i = 0; i < 5; i++) { printf("arr[%d] = %d, Address: %p\n", i, *(ptr + i), (ptr + i)); } return 0; }

Example 2: Pointer Increment

#include <stdio.h> int main() { int arr[] = {100, 200, 300}; int *ptr = arr; printf("Value: %d, Address: %p\n", *ptr, ptr); ptr++; // Move to next element printf("Value: %d, Address: %p\n", *ptr, ptr); ptr++; // Move to next element printf("Value: %d, Address: %p\n", *ptr, ptr); return 0; }
Important: When you add 1 to a pointer, it moves by the size of the data type it points to (e.g., int pointer moves by 4 bytes).

Multilevel Pointers

Pointer to Pointer

A pointer to pointer stores the address of another pointer.

int **ptr; // Pointer to pointer (double pointer) int ***ptr; // Pointer to pointer to pointer (triple pointer)

Example: Double Pointer

#include <stdio.h> int main() { int x = 100; int *ptr = &x; // Pointer to x int **pptr = &ptr; // Pointer to pointer printf("Value of x: %d\n", x); printf("Value using ptr: %d\n", *ptr); printf("Value using pptr: %d\n", **pptr); printf("\nAddress of x: %p\n", &x); printf("Value in ptr: %p\n", ptr); printf("Address of ptr: %p\n", &ptr); printf("Value in pptr: %p\n", pptr); return 0; }

Memory Visualization

x Value: 100 Addr: 0x1000
ptr Value: 0x1000 Addr: 0x2000
pptr Value: 0x2000 Addr: 0x3000

Use Cases

  • 2D array manipulation
  • Function arguments for modifying pointers
  • Dynamic memory allocation for matrices
  • Linked data structures

Summary - Key Points

Concept Description
Pointer Variable that stores memory address
Declaration data_type *ptr;
& Operator Returns address of a variable
* Operator Dereferences pointer (accesses value)
NULL Pointer Points to nothing (safe initialization)
Void Pointer Generic pointer (can point to any type)
Wild Pointer Uninitialized pointer (dangerous!)
Dangling Pointer Points to freed memory (dangerous!)
Pointer Arithmetic +, -, ++, -- operations on pointers
Double Pointer Pointer to pointer (**ptr)
Best Practices:
  • Always initialize pointers
  • Check for NULL before dereferencing
  • Set pointers to NULL after freeing memory
  • Be careful with pointer arithmetic
  • Avoid wild and dangling pointers

Practice Problems

Problem 1: Basic Pointer Operations

Write a program to swap two numbers using pointers. Create a function swap() that takes two integer pointers as parameters.

Problem 2: Array Manipulation

Write a program that uses pointer arithmetic to find the largest element in an integer array of size 10.

Problem 3: Pointer to Pointer

Create a program that uses a double pointer to dynamically allocate a 2D array of integers (3x3 matrix) and initialize it with values 1-9.

Problem 4: String Reversal

Write a function to reverse a string in-place using two pointers (one at the start and one at the end).

Problem 5: Pointer Comparison

Write a program that declares three integer variables and three pointers. Initialize the pointers and compare their addresses to determine which variable is stored at the lowest memory address.

Problem 6: Void Pointer

Create a generic print function using void pointer that can print integer, float, or character values based on a type parameter.