C Pointers
A pointer is a variable that stores a memory address. With a pointer, code can reach a variable that lives somewhere else: a function can change its caller's variables, a loop can walk through an array, and a program can build lists that grow.
Declaring and using a pointer
A star in the declaration makes a pointer: int *p is "a pointer to an int". &x gives the address of x. A star in front of a pointer, *p, reaches the value it points at; this is called dereferencing.
#include <stdio.h>
int main(void) {
int x = 10;
int *p = &x; // p holds the address of x
printf("x = %d\n", x);
printf("*p = %d\n", *p);
*p = 25; // change x through p
printf("x = %d\n", x);
return 0;
}x = 10 *p = 10 x = 25
Keep the two meanings of the star apart: in a declaration it says "this is a pointer"; in an expression it means "the value at this address".
Changing a caller's variables
Arguments are copied into functions, so a function cannot change the caller's variables directly. Passing their addresses solves that. This is the classic swap:
#include <stdio.h>
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
int main(void) {
int a = 4, b = 9;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}a = 9, b = 4
Pointers and arrays
An array's name is the address of its first element. Adding 1 to a pointer moves it to the next element, whatever the element's size. This is pointer arithmetic:
#include <stdio.h>
int main(void) {
int nums[5] = {1, 2, 3, 4, 5};
int sum = 0;
for (int *q = nums; q < nums + 5; q++) {
sum += *q;
}
printf("Sum: %d\n", sum);
printf("nums[2] = %d, *(nums + 2) = %d\n", nums[2], *(nums + 2));
printf("A pointer uses %zu bytes here.\n", sizeof(int *));
return 0;
}Sum: 15 nums[2] = 3, *(nums + 2) = 3 A pointer uses 4 bytes here.
nums[2] and *(nums + 2) mean exactly the same thing: indexing is pointer arithmetic in disguise. When an array is passed to a function, the function receives a pointer to the first element, so it does not know the array's size; pass the size as another parameter.
NULL
A pointer that points nowhere is set to NULL. Dereferencing NULL, or a pointer that was never set, crashes the program or worse, so check before using a pointer that may be empty: if (p != NULL). Functions such as malloc, fopen and strchr return NULL when they fail or find nothing.
Practice exercises
- Write a function that takes the address of an
intand doubles the value. - Write a function that finds both the smallest and the largest value of an array and gives them back through two pointer parameters.
- Print the elements of an array by moving a pointer instead of using an index.
- Print a string one character at a time using a
char *that moves until it reaches'\0'.