the address-of operator (&)
The address-of operator, written as a single ampersand &, answers 'where does this live?'. You put it in front of a variable and it hands you that variable's address — the box number, not the box's contents. So if x sits at 0x1000, then &x is the value 0x1000.
&x produces a pointer of the matching type: if x is an int, &x has type int *, ready to store in an int *p. It only works on something that actually has an address — a named variable, an array element, a struct field — and not on a temporary or a literal: &5 and &(a + b) are errors, because 5 and a + b never live in a definable box. The two most common uses are taking the address of a local to let a function write back into it (the classic out-parameter, as scanf("%d", &n) does), and capturing where something is so you can store or pass that location.
Think of & and * as opposites: & turns a value's name into its address, and * turns an address back into the value, so *&x is just x again. & is also why C can fake 'pass by reference' even though it only ever passes by value — you pass &x (a copy of the address) and the callee writes through it with *p.
void set(int *p) { *p = 42; } int n = 0; set(&n); — after the call n is 42. We passed &n, the address of n; inside set, *p = 42 reached back across the call and wrote n.
&n hands the address across; *p writes through it — C's 'pass by reference' trick.
The same symbol & also means bitwise AND when placed between two values (a & b), and && is logical AND — three different operators sharing the character. As address-of it is unary, sitting in front of a single operand.