The preprocessor was introduced to C around 1973 at the urging of Alan Snyder and also in recognition of the usefulness of the file inclusion mechanisms available in BCPL and PL/I.
The first version offered file inclusion via #include and parameterless string replacement macros via #define.
It was extended shortly after, firstly by Mike Lesk and then by John Reiser, to add arguments to macros and to support conditional compilation.
The inclusion may be logical in the sense that the resulting content may not be stored on disk and certainly is not overwritten to the source file.
In the following example code, the preprocessor replaces the line #include
If whitespace is present, the macro is interpreted as object-like with everything starting at the first parenthesis included in the replacement text.
Note that text of string literals and comments is not parsed as tokens and is therefore ignored for macro expansion.
The following macro, DEBUGPRINT, formats and prints a message with the file name and line number.
Compilers running in non-standard mode must not set these macros or must define others to signal the differences.
[8] This allows code, including preprocessor commands, to compile only when targeting Windows systems.
stringizing operator), denoted by # converts a token into a string literal, escaping any quotes or backslashes as needed.
[9] This allows binary resources (like images) to be included into a program without requiring processing by external tools like xxd -i and without the use of string literals which have a length limit on MSVC.
Similarly to xxd -i the directive is replaced by a comma separated list of integers corresponding to the data of the specified resource.
Apart from the convenience, #embed is also easier for compilers to handle, since they are allowed to skip expanding the directive to its full form due to the as-if rule.
Implementation-defined parameters use a form similar to attribute syntax (e.g., vendor::attr) but without the square brackets.
For instance, a pragma is often used to allow suppression of error messages, manage heap and stack debugging and so on.
Many implementations (such as the C compilers by GNU, Intel, Microsoft and IBM) provide a non-standard directive to print a message without aborting, typically to warn about the use of deprecated functionality.
Notable examples include use with the (deprecated) imake system and for preprocessing Fortran.
[14] Intel offers a Fortran preprocessor, fpp, for use with the ifort compiler, which has similar capabilities.
The "traditional mode" (acting like a pre-ISO C preprocessor) is generally more permissive and better suited for such use.
Text substitution has a relatively high risk of causing a software bug as compared to other programming constructs.
If the actual expressions have constant value, then multiple evaluation is not problematic from a logic standpoint even though it can affect runtime performance.
To mitigate this problem, a macro should bracket all expressions and substitution variables: The C preprocessor is not Turing-complete, but comes close.
Due to its limitations, C and C++ language features have been added over the years to minimize the value and need for the preprocessor.
For a long time, a preprocessor macro provided the preferred way to define a constant value.
A newer language construct (since C++11 and C23), constexpr allows for declaring a compile-time constant value that need not consume runtime memory.
Many contend that resulting code is easier to maintain since there is only one file for a module; not both a header and a body.