5.14.1 Preprocessor Directives

The XC8 accepts several specialized preprocessor directives, in addition to the standard directives. All of these are tabulated below.

Table 5-15. Preprocessor Directives
DirectiveMeaningExample
#Preprocessor null directive, do nothing.#
#defineDefine preprocessor macro.
#define SIZE (5)
#define FLAG
#define add(a,b) ((a)+(b))
#elifShort for #else #if.see #ifdef
#elseConditionally include source lines.see #if
#endifTerminate conditional source inclusion.see #if
#errorGenerate an error message.#error Size too big
#ifInclude source lines if constant expression true.
#if SIZE < 10
    c = process(10)
#else
    skip();
#endif
#ifdefInclude source lines if preprocessor symbol defined.
#ifdef FLAG
    do_loop();
#elif SIZE == 5
    skip_loop();
#endif
#ifndefInclude source lines if preprocessor symbol not defined.
#ifndef FLAG
    jump();
#endif
#includeInclude text file into source.
#include <stdio.h>
#include “project.h”
#lineSpecify line number and filename for listing#line 3 final
#nn filename(where nn is a number, and filename is the name of the source file) the following content originated from the specified file and line number.#20 init.c
#pragmaCompiler specific options.See the Pragma Directives section in this guide.
#undefUndefines preprocessor symbol.#undef FLAG
#warningGenerate a warning message.#warning Length not set

Macro expansion using arguments can use the # operator to convert an argument to a string and the ## operator to concatenate arguments. If two expressions are being concatenated, consider using two macros in case either expression requires substitution itself; for example

#define __paste1(a,b)   a##b
#define __paste(a,b)    __paste1(a,b)

lets you use the paste macro to concatenate two expressions that themselves might require further expansion. Remember that once a macro identifier has been expanded, it will not be expanded again if it appears after concatenation.

Preprocessor macros can take a variable number of arguments, just like C functions. Use an ellipsis (…) after any named arguments to define a variable argument list. Use the special token __VA_ARGS__ to expand this argument list in the macro replacement text. For example, the following PIC18 code places a variable number of words into program memory. Note that the arguments were converted to strings using the # operator so as to be usable in the __asm() statement.
#define PLACE_WORDS(...) \
__asm("PSECT cdata,class=CODE,reloc=2,noexec"); \
__asm("DW " #__VA_ARGS__)
Call this macro in the usual way, passing it as many arguments as are required, for example:
PLACE_WORDS(0x100, 1, 223, 0x30F0);