Pointers
A pointer holds an address. &x takes the address of x, and *p reads or writes what p points at. Adding 1 to a pointer moves it by one element, not one byte. In firmware, a pointer to a fixed address is how C reaches a hardware register.
Addresses, & and *
Every variable sits at an address in memory. &x gives that address, and a pointer variable such as int *px = &x; stores it. Writing *px follows the pointer: *px += 1 changes x itself. This is how a function changes its caller's data, since arguments are otherwise copies.
Pointer arithmetic
A pointer's type says what it points at, and arithmetic counts in elements of that type. If p points at a uint16_t, p++ adds 2 to the address, and p[i] means *(p + i). That is why array indexing and pointers are so closely related. A pointer that holds NULL points at nothing, and reading through it is undefined behaviour.
#include <stddef.h>#include <stdint.h>#include <stdio.h>int main(void) { int x = 7; int *px = &x; /* px holds the address of x */ *px += 1; /* change x through px */ printf("x = %d\n", x); uint16_t samples[3] = {100, 200, 300}; uint16_t *p = samples; /* points at samples[0] */ *p = 150; p++; /* moves one uint16_t: 2 bytes */ printf("*p = %u\n", (unsigned)*p); printf("step = %u bytes\n", (unsigned)((char *)p - (char *)samples)); printf("samples[0] = %u\n", (unsigned)samples[0]); int *none = NULL; if (none == NULL) { puts("none is NULL: never dereference it"); } return 0;}
x = 8 *p = 200 step = 2 bytes samples[0] = 150 none is NULL: never dereference it
A register at a fixed address
Peripheral registers sit at addresses given in the chip's reference manual. Casting that number to a pointer and dereferencing it reads or writes the register. volatile tells the compiler that every access matters; a later insight, volatile and const, explains why.
#include <stdint.h>/* Example address: take the real one from your chip's reference manual. */#define GPIO_OUT (*(volatile uint32_t *)0x40020014u)void led_on(void) { GPIO_OUT |= 1u << 5; /* set bit 5 of the output register */}