* and & as type modifiers
int i declares an int.
int* p declares a pointer to an int.
int& r = i declares a reference to an int, and initializes it to refer to i.
C++ only. Note that references must be assigned at initialization, therefore int& r; is not possible.
Similarly:
void foo(int i) declares a function taking an int (by value, i.e. as a copy).
void foo(int* p) declares a function taking a pointer to an int.
void foo(int& r) declares a function taking an int by reference. (C++ only)
* and & as operators
foo(i) calls foo(int). The parameter is passed as a copy.
foo(*p) dereferences the int pointer p and calls foo(int) with the int pointed to by p.
foo(&i) takes the address of the int i and calls foo(int*) with that address.
(tl;dr) So in conclusion, depending on the context:
* can be either the dereference operator or part of the pointer declaration syntax.
& can be either the address-of operator or (in C++) part of the reference declaration syntax.
Note that * may also be the multiplication operator, and & may also be the bitwise AND operator.
funct(int a)
Creates a copy of a
funct(int* a)
Takes a pointer to an int as input. But makes a copy of the pointer.
funct(int& a)
Takes an int, but by reference. a is now the exact same int that was given. Not a copy. Not a pointer.