14. Conditional Compilation.

Conditional compilation is useful for things like machine-dependencies, debugging, and for setting certain options at compile-time. Beware of conditional compilation. Various controls can easily combine in unforeseen ways. If you #ifdef machine dependencies, make sure that when no machine is specified, the result is an error, not a default machine. (Use "#error" and indent it so it works with older compilers.) If you #ifdef optimizations, the default should be the unoptimized code rather than an uncompilable program. Be sure to test the unoptimized code.

Note that the text inside of an #ifdeffed section may be scanned (processed) by the compiler, even if the #ifdef is false. Thus, even if the #ifdeffed part of the file never gets compiled (e.g., #ifdef COMMENT), it cannot be arbitrary text.

Put #ifdefs in header files instead of source files when possible. Use the #ifdefs to define macros that can be used uniformly in the code. For instance, a header file for checking memory allocation might look like (omitting definitions for REALLOC and FREE):

	#ifdef DEBUG
		extern void *mm_malloc();
	#	define MALLOC(size) (mm_malloc(size))
	#else
		extern void *malloc();
	#	define MALLOC(size) (malloc(size))
	#endif

Conditional compilation should generally be on a feature-by-feature basis. Machine or operating system dependencies should be avoided in most cases.

	#ifdef BSD4
		long t = time ((long *)NULL);
	#endif
The preceding code is poor for two reasons: there may be 4BSD systems for which there is a better choice, and there may be non-4BSD systems for which the above is the best code. Instead, use define symbols such as TIME_LONG and TIME_STRUCT and define the appropriate one in a configuration file such as config.h.


upcontents previousMacros nextDebugging