C Pointers
What is a Pointer?
A pointer is a variable that stores the memory address of another variable. Pointers are one of C's most powerful features — they enable dynamic memory allocation, efficient array handling, and passing variables by reference.
&— Address-of operator: gets the memory address of a variable*— Dereference operator: accesses the value at the address stored in a pointer
int x = 10;
int *ptr = &x; // ptr holds the address of x
printf("%d\n", x); // 10 — value of x
printf("%p\n", ptr); // address of x (e.g., 0x7fff...)
printf("%d\n", *ptr); // 10 — value at the address (dereference)
Pointer Arithmetic
You can perform arithmetic on pointers. When you increment a pointer, it moves by the size of the type it points to.
int arr[] = {10, 20, 30};
int *p = arr; // points to arr[0]
p++; // now points to arr[1] (moves 4 bytes for int)
printf("%d", *p); // 20
NULL Pointer
A NULL pointer is a pointer that doesn't point to any valid memory location. Always initialize pointers to NULL if not assigning an address immediately, and check before dereferencing.
#include <stdio.h>
int main() {
int x = 42;
int *ptr = &x; // ptr stores address of x
printf("Value of x: %d\n", x);
printf("Address of x: %p\n", (void*)&x);
printf("Value of ptr: %p\n", (void*)ptr); // same as &x
printf("Dereference *ptr: %d\n", *ptr); // 42
// Modify x through pointer
*ptr = 100;
printf("x after *ptr=100: %d\n", x); // 100
// Pointer to pointer
int **pptr = &ptr;
printf("\nPointer to pointer:\n");
printf("**pptr = %d\n", **pptr); // 100
// Size of pointer (same regardless of type on 64-bit)
printf("\nsizeof(int*): %zu\n", sizeof(int*));
printf("sizeof(double*): %zu\n", sizeof(double*));
printf("sizeof(char*): %zu\n", sizeof(char*));
return 0;
}
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *p = arr; // array name = pointer to first element
// Traverse array using pointer arithmetic
printf("Array using pointer arithmetic:\n");
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d (address: %p)\n", i, *(p + i), (void*)(p + i));
}
// Pointer increment
printf("\nUsing p++:\n");
p = arr; // reset to start
while (p < arr + 5) {
printf("%d ", *p);
p++;
}
printf("\n");
// Pointer difference
int *start = arr;
int *end = arr + 4;
printf("\nPointer difference: %td elements\n", end - start); // 4
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int main() {
// Pointer to function: return_type (*name)(param_types)
int (*operation)(int, int);
operation = add;
printf("add(5, 3) = %d\n", operation(5, 3)); // 8
operation = sub;
printf("sub(5, 3) = %d\n", operation(5, 3)); // 2
operation = mul;
printf("mul(5, 3) = %d\n", operation(5, 3)); // 15
// NULL pointer — always check before dereferencing
int *ptr = NULL;
if (ptr != NULL) {
printf("Value: %d\n", *ptr);
} else {
printf("Pointer is NULL — safe to skip dereference\n");
}
// Dynamic allocation returns NULL on failure
int *arr = (int*)malloc(5 * sizeof(int));
if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
arr[0] = 42;
printf("arr[0] = %d\n", arr[0]);
free(arr);
return 0;
}
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.