Ich benutze defines meistens zur Umdefinition von Zahlenwerten, z.B. für die Baudrate der UART (#define UART_BAUD_RATE 57600) oder für Berechnungen oder zur Zusammenfassung von Rechenoperationen (z.B #define UART_BAUD_SELECT (F_CPU/(USS_BAUD_RATE*16l)-1) )
Bei diesem Beispiel bräuchte ich z.B. zur Anpassung der Baudrate nur in der uart.h den Wert zu ändern und bin fertig.

Gelegentlich sind auch if-Abfragen auf Präprozessor-Ebene ganz nützlich. Beim ATMega128 habe ich z.B. zwei COM-Schnittstellen. Um meine uart.c für beide Schnittstellen benutzen zu können, habe ich mir folgenden Konstrukt gebastelt:

Code:
#define COM_PORT 0

#if COM_PORT
		#define UDRX			UDR1
		#define UCSRXA  		UCSR1A
		#define UCSRXB  		UCSR1B
		#define UCSRXC  		UCSR1C
		#define UBRRXL  		UBRR1L
		#define UBRRXH  		UBRR1H
		#define SIG_UARTX_DATA	SIG_UART1_DATA
		#define SIG_UARTX_RECV	SIG_UART1_RECV
	#else
		#define UDRX			UDR0
		#define UCSRXA  		UCSR0A
		#define UCSRXB  		UCSR0B
		#define UCSRXC  		UCSR0C	
		#define UBRRXL  		UBRR0L
		#define UBRRXH  		UBRR0H
		#define SIG_UARTX_DATA	SIG_UART0_DATA
		#define SIG_UARTX_RECV	SIG_UART0_RECV
	#endif
Um den Code auf die andere Schnittstellen anzupassen, brauche ich nur noch das Makro COM_PORT zu ändern.

Man darf natürlich mit Makros nicht übertreiben. Komplexere Sachen gehören in eine Funktion. Und ganz tabu sind Sachen wie
Code:
#define wenn if
#define dann else
Damit fängt man dann an, eine neue Programmiersprache zu basteln.
Generell würde ich keine Makros basteln, die Schlüsselwörter von C enthalten. Da kann man sich besser eine inline-Funktion basteln, wenn man einen kurzen Code hat, den man mehrmals aufrufen möchte.

Gruß,
askazo