|
C Preprocessor - Basic Infomation (GNU Preprocessor) 2014-12-16    Piotr Romaniuk, Ph.D. Contents
How Preprocessor Works The preprocessor is run before compilation of C/C++ source files. It is responsible for:
Please note that the preprocessor does not recognize keywords of the programming languages (C/C++), because they are compiled in next stage. Moreover, preprocessing is some kind of text transformation and its done in this domain. The preprocessor has simplified expressions and limited number of operators. They are generaly oriented to comparison integer values.
There is no doubt that the most interesting and powerful feature of the preprocessor is macrodefinition.
They can replace parts of a text by another textual contents. Macrodefinition processing is explained
in details in another page devoted to the preprocessor.
There are two kinds of macros with or without arguments:
#define MY_TABLE_SIZE 256 #define SATURATE(x) (x>255)? 255 : (x) Note that there is no space between name of macro and opening parenthesis! If you insert the space the macro is recognized as object-like (i.e. argument-less) and argument list becomes part of the expansion: //incorrect definition because of the space after macro name: #define SATURATE (x) (x>255)? 255 : (x) //usage: y = SATURATE(w); //is expanded to: y = (x) (x>255)? 255 : (x)(w); //instead of expected: y = (w>255)? 255 : (w);
Variable Number of Arguments (Variadic Macros) In a case of function-like macro, number of used arguments must be consistent with the number that were specified in the definition. Any inconsistence generates preprocessing error. #define MACRO(x,y) (x)+(y) w = MACRO(1); // generates the error: // error: macro "MACRO" requires 2 arguments, but only 1 given w = MACRO(1,2,3); // error: macro "MACRO" passed 3 arguments, but takes only 2 Of course, it is good that the preprocessor checks this consistency but sometimes it is useful to have a macro with not specified (variable) number of arguments. Here is the syntax for this: #define DBG_MSG(level,format_string,...) printf( "<%d>" format_string, level,__VA_ARGS__ ) As you can see, variable number of arguments is signaled by ellipsis. In a place when they are needed __VA_ARGS__ symbol is used. After some trials of the example presented above, it can be noticed that format_string argument must be followed by at least one. Otherwise, the error is generated: error: expected expression before ')' token #define DBG_MSG(level,format_string,...) printf( "<%d>" format_string, level,__VA_ARGS__ ) ^ note: in expansion of macro DBG_MSG DBG_MSG(1, "some_string") ^ Concatenation operator (double hash - ##) can help is this problem. It will be discussed below. Here it can be interpretted as merging __VA_ARGS__ with comma. When __VA_ARGS__ is empty the comma is dropped. #define DBG_MSG(level,format_string,...) printf( "<%d>" format_string, level, ## __VA_ARGS__ )
Transformation to Strings (Stringification)
The preprocessor provides a feature of transformation the symbol to a string. Let's take an example of a table that contains
error values and its names (the names are required for printing error messages):
Merging Symbols (Concatenation)
The concatenation operator (double hash) merges two tokens in the macro expansion:
It can be surprising when another preprocessor symbol is used as argument in the macro.
The result is that the symbol is not expanded before concatenation and its name is inserted.
In order to achieve expected aim, another extra macro is required. It will be inserted in expansion chain,
hence it expands argument before it is used by concatenation.
|
||||||