Pointers in C allow variables to hold the memory addresses of other variables and data types. Pointers use the asterisk (*) and ampersand (&) operators - * accesses the value at a memory address, while & returns the memory address of a variable. Pointers are useful for passing arguments to functions, returning multiple values from functions, and accessing arrays through a single pointer variable. Pointer arithmetic increments or decrements a pointer by the size of its data type. Pointer-to-pointers allow pointers to hold the addresses of other pointer variables. Proper initialization and boundary checking is important to avoid crashes with pointers.