Quizá me deje algo, así que posiblemente luego quieras revisarlo en algun libro o similar.
Typedef: define un tipo. Simple y llanamente. le dice al compilador que un tipo se refiere a otro.
typedef int mis_enteros
mis_enteros a;
//equivalente a
int a;
de esa forma, defino que el tipo mis_enteros es un entero. Sobretodo se usa con estructuras.
#define: Funciona de la siguiente forma:
#define PI 3.14
Entonces, en cada lugar donde en tu código aparezca PI, se sustituirá por un 3.14 (cuidado con los defines, los nombres de lo que defines y demás, son armas de doble filo)
ifdef y endif: Si algo está definido y final de la definición. Suelen ir en conjunción con define, sobretodo se usan para evitar incluir varias veces la misma librería.
#ifdef PI
#define TAU 2*PI
#endif
Por otro lado, también verás ifndef, que viene a ser lo mismo, pero si NO está definido.
Espero que resulte útil