- C preprocessor
-
The C preprocessor (cpp) is the preprocessor for the C and C++ computer programming languages. The preprocessor handles directives for source file inclusion (
#include
), macro definitions (#define
), and conditional inclusion (#if
).In many C implementations, it is a separate program invoked by the compiler as the first part of translation.
The language of preprocessor directives is agnostic to the grammar of C, so the C preprocessor can also be used independently to process other kinds of text files.
Contents
Phases
The first four (of eight) phases of translation specified in the C Standard are:
- Trigraph replacement: The preprocessor replaces trigraph sequences with the characters they represent.
- Line splicing: Physical source lines that are continued with escaped newline sequences are spliced to form logical lines.
- Tokenization: The preprocessor breaks the result into preprocessing tokens and whitespace. It replaces comments with whitespace.
- Macro expansion and directive handling: Preprocessing directive lines, including file inclusion and conditional compilation, are executed. The preprocessor simultaneously expands macros and, in the 1999 version of the C standard, handles
_Pragma
operators.
Including files
One of the most common uses of the preprocessor is to include another file:
#include <stdio.h> int main(void) { printf("Hello, world!\n"); return 0; }
The preprocessor replaces the line
#include <stdio.h>
with the system header file of that name, which declares theprintf()
function among other things. More precisely, the entire text of the file 'stdio.h' replaces the#include
directive.This can also be written using double quotes, e.g.
#include "stdio.h"
. If the filename is enclosed within angle brackets, the file is searched for in the standard compiler include paths. If the filename is enclosed within double quotes, the search path is expanded to include the current source directory. C compilers and programming environments all have a facility which allows the programmer to define where include files can be found. This can be introduced through a command line flag, which can be parameterized using a makefile, so that a different set of include files can be swapped in for different operating systems, for instance.By convention, include files are given a .h extension, and files not included by others are given a .c extension. However, there is no requirement that this be observed. Occasionally you will see files with other extensions included: files with a .def extension may denote files designed to be included multiple times, each time expanding the same repetitive content;
#include "icon.xbm"
is likely to refer to an XBM image file (which is at the same time a C source file).#include
often compels the use of#include
guards or#pragma once
to prevent double inclusion.Conditional compilation
The
#if
,#ifdef
,#ifndef
,#else
,#elif
and#endif
directives can be used for conditional compilation.#if VERBOSE >= 2 print("trace message"); #endif
Most compilers targeting Microsoft Windows implicitly define
_WIN32
[1]. This allows code, including preprocessor commands, to compile only when targeting Windows systems. A few compilers defineWIN32
instead. For such compilers that do not implicitly define the_WIN32
macro, it can be specified on the compiler's command line, using-D_WIN32
.#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */ # include <unistd.h> #elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */ # include <windows.h> #endif
The example code tests if a macro
__unix__
is defined. If it is, the file<unistd.h>
is then included. Otherwise, it tests if a macro_WIN32
is defined instead. If it is, the file<windows.h>
is then included.A more complex
#if
example can use operators, for example something like:#if !(defined __LP64__ || defined __LLP64__) || defined _WIN32 && !defined _WIN64 // we are compiling for a 32-bit system #else // we are compiling for a 64-bit system #endif
Translation can also be caused to fail by using the
#error
directive:#if RUBY_VERSION == 190 # error 1.9.0 not supported #endif
Macro definition and expansion
There are two types of macros, object-like and function-like. Object-like macros do not take parameters; function-like macros do. The generic syntax for declaring an identifier as a macro of each type is, respectively:
#define <identifier> <replacement token list> // object-like macro #define <identifier>(<parameter list>) <replacement token list> // function-like macro, note parameters
Note that the function-like macro declaration must not have any whitespace between the identifier and the first, opening, parenthesis. If whitespace is present, the macro will be interpreted as object-like with everything starting from the first parenthesis added to the token list.
Whenever the identifier appears in the source code it is replaced with the replacement token list, which can be empty. For an identifier declared to be a function-like macro, it is only replaced when the following token is also a left parenthesis that begins the argument list of the macro invocation. The exact procedure followed for expansion of function-like macros with arguments is subtle.
Object-like macros were conventionally used as part of good programming practice to create symbolic names for constants, e.g.
#define PI 3.14159
... instead of hard-coding those numbers throughout one's code. An alternative in both C and C++, especially in situations in which a pointer to the number is required, is to apply the
const
qualifier to a global variable. This causes the value to be stored in memory, instead of being substituted by the preprocessor.An example of a function-like macro is:
#define RADTODEG(x) ((x) * 57.29578)
This defines a radians to degrees conversion which can be written subsequently, e.g.
RADTODEG(34)
orRADTODEG (34)
. This is expanded in-place, so the caller does not need to litter copies of the multiplication constant all over the code. The macro here is written as all uppercase to emphasize that it is a macro, not a compiled function. Note the second x is enclosed in its own pair of parentheses. This avoids calculations in an undesired order of operations if an expression instead of a single value is passed.Certain symbols are required to be defined by an implementation during preprocessing. These include
__FILE__
and__LINE__
, predefined by the preprocessor itself, which expand into the current file and line number. For instance the following:// debugging macros so we can pin down message origin at a glance #define WHERESTR "[file %s, line %d]: " #define WHEREARG __FILE__, __LINE__ #define DEBUGPRINT2(...) fprintf(stderr, __VA_ARGS__) #define DEBUGPRINT(_fmt, ...) DEBUGPRINT2(WHERESTR _fmt, WHEREARG, __VA_ARGS__) //... DEBUGPRINT("hey, x=%d\n", x);
prints the value of
x
, preceded by the file and line number to the error stream, allowing quick access to which line the message was produced on. Note that theWHERESTR
argument is concatenated with the string following it.The first C Standard specified that the macro
__STDC__
be defined to 1 if the implementation conforms to the ISO Standard and 0 otherwise, and the macro__STDC_VERSION__
defined as a numeric literal specifying the version of the Standard supported by the implementation. Standard C++ compilers support the__cplusplus
macro. Compilers running in non-standard mode, with advanced or reduced language features that may be conflicting with the essential standard, might not set these macros or should define others to exhibit the differences.Other Standard macros include
__DATE__
and__TIME__
, which expand to the date and time of translation respectivelyThe second edition of the C Standard, C99, added support for
__func__
, which contains the name of the function definition within which it is contained, but because the preprocessor is agnostic to the grammar of C, this must be done in the compiler itself using a variable local to the function.Macros that can take a varying number of arguments (variadic macros) are not allowed in C89, but were introduced by a number of compilers and standardised in C99. Variadic macros are particularly useful when writing wrappers to variable parameter number functions, such as
printf
, for example when logging warnings and errors.One little-known usage pattern of the C preprocessor is known as "X-Macros".[2][3][4] An X-Macro is a header file. Commonly these use the extension ".def" instead of the traditional ".h". This file contains a list of similar macro calls, which can be referred to as "component macros". The include file is then referenced repeatedly.
Compiler-specific predefined macros are usually listed in the compiler documentation, although this is often incomplete.
Some compilers can be made to dump at least some of their useful predefined macros, for example:
- GNU C Compiler
gcc -dM -E - < /dev/null
- HP-UX ansi C compiler
cc -v fred.c
(wherefred.c
is a simple test file)- SCO OpenServer C compiler
cc -## fred.c
(wherefred.c
is a simple test file)- Sun Studio C/C++ compiler
cc -## fred.c
(wherefred.c
is a simple test file)- IBM AIX XL C/C++ compiler
cc -qshowmacros -E fred.c
(wherefred.c
is a simple test file)
User-defined compilation errors and warnings
The
#error
directive outputs a message through the error stream.#error "Gaah!"
Implementations
Compiler-specific preprocessor features
The
#pragma
directive is a compiler specific directive which compiler vendors may use for their own purposes. For instance, a#pragma
is often used to allow suppression of specific error messages, manage heap and stack debugging and so on.C99 introduced a few standard
#pragma
directives, taking the form#pragma STDC ...
, which are used to control the floating-point implementation.- Many implementations do not support trigraphs or do not replace them by default.
- Many implementations (including, e.g., the C-compilers by GNU, Intel, and IBM) provide a non-standard
#warning
directive to print out a warning message in the output, but not stop the compilation process. A typical use is to warn about the usage of some old code, which is now deprecated and only included for compatibility reasons, e.g.:
#warning "Do not use ABC, which is deprecated. Use XYZ instead."
- Some Unix preprocessors traditionally provided "assertions", which have little similarity to assertions used in programming.[5]
- GCC provides
#include_next
for chaining headers of the same name.[6] - Objective-C preprocessors have
#import
, which is like#include
but only includes the file once.
Uses
As a general-purpose preprocessor (GPP)
Since the C preprocessor can be invoked independently to process files other than those containing to-be-compiled source code, it can also be used as a "general purpose preprocessor" (GPP) for other types of text processing. One particularly notable example is the now-deprecated imake system.
GPP does work acceptably with most assembly languages. GNU mentions assembly as one of the target languages among C, C++ and Objective-C in the documentation of its implementation of the preprocessor. This requires that the assembler syntax not conflict with GPP syntax, which means no lines starting with
#
and that double quotes, which cpp interprets as string literals and thus ignores, don't have syntactical meaning other than that.However, since the C preprocessor does not have features of other preprocessors, such as recursive macros, selective expansion according to quoting, string evaluation in conditionals, and Turing completeness, it is very limited in comparison to a more modern, true GPP such as m4. For instance, the inability to define macros using other macros requires code to be broken into more sections than would be required.
See also
References
- ^ List of predefined ANSI C and Microsoft C++ implementation macros.
- ^ Wirzenius, Lars. C "Preprocessor Trick For Implementing Similar Data Types". Retrieved January 9, 2011
- ^ Meyers, Randy (May 2001). "The New C: X Macros". Dr. Dobb's Journal. http://www.ddj.com/cpp/184401387. Retrieved 1 May 2008.
- ^ Beal, Stephan (August 2004). Supermacros. http://wanderinghorse.net/computing/papers/#supermacros. Retrieved 27 October 2008.
- ^ GCC Obsolete features
- ^ http://gcc.gnu.org/onlinedocs/cpp/Wrapper-Headers.html
External links
- ISO/IEC 9899. The official C:1999 standard, along with defect reports and a rationale. As of 2005 the latest version is ISO/IEC 9899:TC2.
- GNU CPP online manual
- Visual Studio .NET preprocessor reference
- Pre-defined C/C++ Compiler Macros project: lists "various pre-defined compiler macros that can be used to identify standards, compilers, operating systems, hardware architectures, and even basic run-time libraries at compile-time"
C programming language Compilers Libraries Features Select descendants C and other languages Categories:- C programming language
- Transformation languages
- Macro programming languages
Wikimedia Foundation. 2010.