C Programming · Lesson 6 of 10 · Updated ·
Pointers in C — Addresses, Dereferencing and Pointer Arithmetic
A pointer is a variable that stores the address of another variable. That's it. Everything else follows from this one idea.
1. & and *
&x— "address of x"int *p— "p is a pointer to an int"*p— "the value at the address in p" (dereferencing)
#include <stdio.h>
int main(void) {
int x = 10;
int *p = &x;
printf("%d %d\n", x, *p);
*p = 25; /* change x through p */
printf("%d\n", x);
printf("%d\n", p == &x);
return 0;
}
10 10
25
1
(Actual addresses change every run, so we compare them instead of printing them.)
2. Pointers and arrays
The name of an array is (in most expressions) a pointer to its first element. And a[i] is exactly *(a + i).
#include <stdio.h>
int main(void) {
int a[5] = {10, 20, 30, 40, 50};
int *p = a; /* same as &a[0] */
printf("%d %d %d\n", *p, *(p + 2), p[4]);
p++; /* move to the next int */
printf("%d\n", *p);
printf("%d\n", (int)(&a[4] - &a[0])); /* distance in elements */
return 0;
}
10 30 50
20
4
Pointer arithmetic
p + 1 moves by sizeof(type) bytes, not 1 byte. For an int * that's 4 bytes; for a double *, 8 bytes. You can:
- add/subtract an integer (
p + 2,p--) - subtract two pointers into the same array (gives the number of elements between them)
- compare pointers
You can't add two pointers.
3. NULL and safety
int *p = NULL; /* points nowhere */
if (p != NULL) {
printf("%d", *p);
}
- Dereferencing NULL crashes the program (segmentation fault).
- A wild pointer is uninitialised (points anywhere) — always initialise pointers.
- A dangling pointer points to memory that was freed or a local variable that no longer exists.
4. Pointer to pointer
#include <stdio.h>
int main(void) {
int x = 7;
int *p = &x;
int **pp = &p;
printf("%d %d %d\n", x, *p, **pp);
**pp = 99;
printf("%d\n", x);
return 0;
}
7 7 7
99
Used for dynamic 2D arrays and when a function must change a pointer (e.g. inserting at the head of a linked list).
5. const and pointers
| Declaration | Can change the value? | Can point elsewhere? |
|---|---|---|
const int *p | ✗ | ✓ |
int *const p | ✓ | ✗ |
const int *const p | ✗ | ✗ |
Read it right to left: int *const p = "p is a const pointer to int".
6. void pointers
void * can hold the address of any type (used by malloc). You must cast it to a real type before dereferencing.
Common mistakes
- Using
*pbeforeppoints to valid memory. - Confusing
*p++(move p, value of old position) with(*p)++(increase the value). - Returning the address of a local variable from a function (dangling pointer).
Quick recap
&x= address;*p= value at address;int *pdeclares a pointer.a[i] == *(a + i);p + 1moves by sizeof(type).- Initialise pointers; check for NULL; avoid dangling pointers.
**pp= pointer to pointer; read const declarations right to left.