140 likes | 450 Views
C and C++ Preprocessing. Preprocessing and Macros. Textual preprocessing of source files C/C++ compilers are actually multi stage programs For example cpp is run first to preprocess your source code /usr/bin/cpp man cpp Can use as free standing macro expander. cpp.
E N D
Preprocessing and Macros • Textual preprocessing of source files • C/C++ compilers are actually multi stage programs • For example cpp is run first to preprocess your source code • /usr/bin/cpp • man cpp • Can use as free standing macro expander
cpp • The “C Preprocessor” • See man page • cpp mysource.c • Or • cpp –DMYFLAG=1 mysource.c • Usually first pass of C and C++ compilers
Source of myfile.c #define FRED 101 #include "junk.txt" #pragma ABC #define SQUARE(A) ((A)*(A)) SQUARE(FRED) int main(){ // normal stuff #ifdef MYFLAG printf("MYFLAG was defined at compile time\n"); #endif } • junk.txt is just another of MY files in the same directory • Use < > instead of “ ” to include system file • For example: /usr/include/stdio.h • Output of: cpp –DMYFLAG myfile.c # 2 "test-cpp.c" 2 # 1 "junk.txt" 1 # 6 "test-cpp.c" 2 #pragma ABC ((101)*(101)) int main(){ // normal stuff printf("MYFLAG was defined at compile time\n"); }
cpp directives • #include <stdio.h> • #include “myfile.c” • #include <iostream> • #if…#endif • #ifdef…#endif • #if…#elif…#else…#endif • #ifndef…#endif • #undef • #define MYLENGTH 10 • #define MYMACRO(A) (A*A) • Need to be careful of spaces and brackets with macros • See const & inline functions as better alternatives
#error • #error error-message • Forces the compiler to stop • In support of debugging • Not the same as an assert which occurs at runtime • Note that you can switch asserts out by using –DNDEBUG at preprocess time
Nesting includes • Need to be careful with nested includes • Especially when writing general purpose systems header files that may be used in different places. • Usual convention is to guard again multiple includes using: #ifndef _NAME_OF_THIS_FILE #define _NAME_OF_THIS_FILE … // the source code goes here #endif
Fooling the system • You can change reported line and filename • #line 100 • #line 100 “myfile” • Resets the reported line counter • Changes variables _ _LINE_ _ and _ _FILE_ _
# and ## • Although # at start of a line is often a comment • # by itself is known as the stringize operator which quotes the subsequent argument • eg #define mkstring(s) # s • ## by itself is known as the paste operator • Concatenates • eg #define concat(x, y) x ## y
#pragma • “pragmatic information” • Used for various proprietary extras…such as execution tracing • See documentation for your compiler • Has potential for use in parallel compiler directives such as OpenMP and others
Predefined cpp macro names • _ _LINE_ _ • _ _FILE_ _ • _ _DATE_ _ • _ _TIME_ _ • Implementation dependent: _ _STDC_ _ _ _cplusplus_ _
m4 • GNU Free Software Foundation Macro Preprocessor • http://www.gnu.org/software/m4/ • Used in the GNU Autoconf project and other places
Other approaches • Make your own preprocessor • Do simple line-based processing • Or extend the language using Lex/Yacc or Flex/Bison specifications • Can add to an existing language syntax/grammar • At some point you cross the line from preprocessing to writing your own compiler…
Preprocessor Summary • Various preprocessors: cpp; m4 etc • Approach been around a while • Allows simple extensions to language • Not very safe • Not very elegant • But quite pragmatic • Use properly parsed language features instead • But still has a role in managing source code