CSCI 243The Mechanics of Programming
Timothy Fossum ([email protected])
TVF / RIT 20195
More About theC Preprocessor
TVF / RIT 20195 CS243: More About CPP
Review: The C Preprocessor (CPP)
• Filter run before the compiler sees the code• Reads source code as input (from stdin or a specified file)
• Applies filtering steps as requested
• Writes resulting code (to stdout or a specified file)
• Can be run as a standalone filter on non-C code• Example: to preprocess assembly language source files
TVF / RIT 20195 CS243: More About CPP
Review: CPP Directives
• Format:
• CPP processes any line beginning with # character• Early C: must be first character on the line
• ANSI C: can have leading whitespace
• Directive name• May be separated from # by whitespace
• Types of directives:• File inclusion
• Macro definition
• Conditional compilation
• Other miscellaneous
[ ws ] # [ ws ] directive [ operands ]
TVF / RIT 20195 CS243: More About CPP
Macros With Parameters
• Syntax:
• Parameter list is a list of identifiers• Called formal parameters (as in function definitions)
• Actual parameters are substituted for formals in body
#define name(params) value
#define SQUARE(a) a * a ...x = SQUARE( 5 );y = SQUARE( x );z = SQUARE( a + 1 );
x = 5 * 5;y = x * x;z = a + 1 * a + 1
TVF / RIT 20195 CS243: More About CPP
Macros vs. Functions
• Can use as “inline” functions:
• Potential for unexpected problems:
#define MAX(a,b) ((a) > (b) ? (a) : (b)) ...x = MAX( 42, 17 );
y = ((i++) > (j) ? (i++) : (j));
x = ((42) > (17) ? (42) : (17));
y = MAX( i++, j );
TVF / RIT 20195 CS243: More About CPP
Macros With Parameters
• #param converts param into a string
#define PRT(n) printf( “The value of “ #n “ is %d\n”, n ) ...PRT( x );
PRT( y + 2 );
printf( “The value of ” “y + 2” “ is %d\n”, y + 2 );
printf( “The value of ” “x” “ is %d\n”, x );
TVF / RIT 20195 CS243: More About CPP
$ cat params.c#include <stdio.h>
#define SQUARE(a) (a) * (a)
#define SQUARE2(a) a * a
#define PRT(n) printf("The value of " #n " is %d\n", n);
int main( void ) { int x = SQUARE(5); // x = (5) * (5) PRT(x); int y = SQUARE(x); // y = (x) * (x) PRT(y); int z = SQUARE(5 + 2); // z = (5 + 2) * (5 + 2) PRT(z); int w = SQUARE2(5 + 2); // w = 5 + 2 * 5 + 2 PRT(w); return( 0 );}
Example: Parameters to Strings (1/2)
TVF / RIT 20195 CS243: More About CPP
Example: Parameters to Strings (2/2)
$ gcc Wall std=c99 o params params.c
$ ./paramsThe value of x is 25The value of y is 625The value of z is 49The value of w is 17
TVF / RIT 20195 CS243: More About CPP
Macros With Parameters
• ## can be used to create symbols
#define FOO(x) ABCx#define BAR(x) ABC##x
...
FOO( hello );
BAR( hello ); ABChello
ABCx
TVF / RIT 20195 CS243: More About CPP
Example: Symbol Generation
$ cat syms.c#include <stdio.h>
#define VAR(x) var##x
int main( void ) { int varA = 10; printf("%d\n", VAR(A)); // VAR(A) > varA return( 0 );}
$ gcc Wall std=c99 o syms syms.c
$ ./syms10
TVF / RIT 20195 CS243: More About CPP
Conditional Compilation
• Original forms:
• Test definition status of a CPP symbol
• Example: “guarding” header files
#ifdef name ...#else ...#endif
#ifndef name ...#else ...#endif
#ifndef _MYFILE_H_#define _MYFILE_H_ ...#endif
myfile.h
TVF / RIT 20195 CS243: More About CPP
Conditional Compilation
• Later implementations added:
• expr is a constant expression• Constants and/or #define’d symbols
• Relational and Boolean operators
#if expr ...#elif expr ...#else ...#endif
TVF / RIT 20195 CS243: More About CPP
Conditional Compilation
• Example use: Linux for Raspberry Pi® systems• Want a common set of sources
• Can’t have code that refers to nonexistent devices
// assumes RPI defined with value == model ##if RPI == 1 || RPI == 1 ... code for older Raspberry Pi models#elif RPI >= 3 ... code for newer models#else ... code for non Pi Linux machines#endif
PDP-11 is a registered trademark of Digital Equipment Corp.
TVF / RIT 20195 CS243: More About CPP
Conditional Compilation
• Special operator: defined(name)• True if name is a defined macro, else false
• Equivalent to:
#if defined(A) && defined(B) && !defined(C) ...#endif
#ifdef A# ifdef B# ifndef C ...# endif# endif#endif
TVF / RIT 20195 CS243: More About CPP
Example: Conditional Compilation (1/2)
$ cat main.c#include <stdio.h>
// to define with debugging: gcc DDEBUG ....int main( void ) {#ifdef DEBUG printf("Debugging\n");#else printf("Not debugging\n");#endif
#ifdef DEBUG #undef DEBUG# ifndef DEBUG printf("Debugging turned off\n");# endif#endif return( 0 );}
TVF / RIT 20195 CS243: More About CPP
Example: Conditional Compilation (1/2)
$ gcc DDEBUG Wall std=c99 o main main.c
$ ./mainDebuggingDebugging turned off
$ gcc Wall std=c99o main main.c
$ ./mainNot debugging
TVF / RIT 20195 CS243: More About CPP
Other Miscellaneous Directives
#error text• Generates a compile-time error message given as text
#if defined( OPTION_A ) ... stuff for option A#elif defined( OPTION_B ) ... stuff for option B#elif defined( OPTION_C ) ... stuff for option C#else #error No option was selected!#endif
TVF / RIT 20195 CS243: More About CPP
Example: Generating Errors
$ cat main.c// generates error: gcc Wall std=c99 c main.c// does not generate error: gcc DTHING ...int main(int argc, char* argv[]) {#ifndef THING #error THING was not defined!#endif return( 0 );}
$ gcc Wall std=c99 c main.cmain.c: In function 'main':main.c:5:4: error: #error THING was not defined!
$ gcc DTHING Wall std=c99 c main.c
$
TVF / RIT 20195 CS243: More About CPP
Other Miscellaneous Directives
#pragma text• Syntax and meaning are implementation-dependent
• Inherently non-portable!
"The '#pragma' command is specified in the ANSI standard to have an arbitrary implementation-defined effect. In the GNU C preprocessor, '#pragma' first attempts to run the game 'rogue'; if that fails, it tries to run the game 'hack'; if that fails, it tries to run GNU Emacs displaying the Tower of Hanoi; if that fails, it reports a fatal error. In any case, preprocessing does not continue."
- Manual for the GNU C preprocessor for GNU CC 1.34.
TVF / RIT 20195 CS243: More About CPP
Hazards of C
• C is exceptionally flexible
• Can do some frightening things with it
• Example: code obfuscation with CPP
TVF / RIT 20195 CS243: More About CPP
obfus.c#define c_ char*#define w_ while(#define ew_ )#define i_ if(#define f_ for(;#define e_ ;){#define r_ return#define n_ int#define p_ (void)printf(#define ep_ );#define db_ }}char ll[]="THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOGS0123456789 ";
char*d[]={"~(((((","bbb~bb","~`|``~","<bbjf>","bbbbb~" ,"<((((<",">````>","dhphdb","|b|bb|","|bb|bb","~bbbb~","bbbjj4", "brjfbb","~`|```", "","b4(4bb","$$$dd8", "","bvjbbb","|bb|``", "","|bbbb|" ,"","bbbb4(" ,"","","","","","`````~" ,"(4b~bb" ,"~$(0`~", "bb<(((","","",">``fb>" ,">`|\"\"|", "~rjfb~", "(8(((<",">b\",0~", "|\".\"\"|","bb~\"\"\"", "~`|\"\"|" ,"~``~b~","~$(0``", "~b~bb~", "~b~\"\"\""," "};n_ main(v,c)c_ *c;{n_ i=1;f_i++<v/**/e_ w((i1)[c]ew_;el(/**/ep_ }r_( 0);}el (){p_"\n"ep_}c_*o(c){c_ z=ll ;i_ c> 31[ll]ew_c=32;w_*z) i_*z++==c ew_ break;r_ d+(zll1 ep_}w(s)c_s;{n_ i,j=0; f_/**/j++<6e_/**/i=0;w_ i[s])l(i++[s],j/**/ep_/**/el(ep_/**/db_ l(c,t){n_ q,j=6;q=(*o(c))[t1];f_/**/j>0; jew_/**/p_"%c",((1<<(j((j<6)?1:0)))&q)?c:' 'ep_}
TVF / RIT 20195 CS243: More About CPP
After gcc E obfus.c# 1 "obfus.c"# 1 "<builtin>"# 1 "<command line>"# 1 "obfus.c"# 12 "obfus.c"char ll[]="THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOGS0123456789 ";
char*d[]={"~(((((","bbb~bb","~`|``~","<bbjf>","bbbbb~" ,"<((((<",">````>","dhphdb","|b|bb|","|bb|bb","~bbbb~","bbbjj4", "brjfbb","~`|```", "","b4(4bb","$$$dd8", "","bvjbbb","|bb|``", "","|bbbb|" ,"","bbbb4(" ,"","","","","","`````~" ,"(4b~bb" ,"~$(0`~", "bb<(((","","",">``fb>" ,">`|\"\"|", "~rjfb~", "(8(((<",">b\",0~", "|\".\"\"|","bb~\"\"\"", "~`|\"\"|" ,"~``~b~","~$(0``", "~b~bb~", "~b~\"\"\""," "};int main(v,c)char* *c;{int i=1;for(;i++<v ;){ w((i1)[c]);el( ); }return( 0);}el (){(void)printf("\n");}char**o(c){char* z=ll ;if( c> 31[ll])c=32;while(*z) if(*z++==c ) break;return d+(zll1 );}w(s)char*s;{int i,j=0; for(; j++<6;){ i=0;while( i[s])l(i++[s],j ); el(); }} l(c,t){int q,j=6;q=(*o(c))[t1];for(; j>0; j) (void)printf("%c",((1<<(j((j<6)?1:0)))&q)?c:' ');}
TVF / RIT 20195 CS243: More About CPP
Operation
$ ./obfus Hello, WorldH H eeeee l l ooooo H H e l l o o H H eeee l l o o HHHHH e l l o o H H e l l o o H H eeeee lllll lllll ooooo
W W ooooo rrrr l dddd W W o o r r l d d W W o o r r l d d W W W o o rrrr l d d W W W o o r r l d d W W ooooo r r lllll dddd
TVF / RIT 20195 CS243: More About CPP
obfus2_full.c (1/4)
/*** Newsgroups: comp.lang.c** From: Richard Heathfield <[email protected]>** Date: Thu, 11 May 2006 14:00:50 +0000** Subject: Re: For loops help** [email protected] said:** ** > Dear everyone,** > ** > Can someone please help me on my HW. I'm trying to write a program** > that will display the following:** > ** > *** > ***** > ******* > ********* > *********** > *********** > ********* > ******* > ***** > *
TVF / RIT 20195 CS243: More About CPP
obfus2_full.c (2/4)
** > I'm having a hard time writing a code for this one. I tried several** > times, but I can't get it to work properly. I live in Japan and I take** > an online C++ course. The instructor lives in the US so whenever I am** > awake, he's asleep. Therefore, I cannot contact him directly when I** > need help. I have to get this program up and running ASAP. I tried** > searching everywhere for help, but there's none except for this group.** > My textbook isn't much of a help either. I WILL GREATLY APPRECIATE THE** > HELP I WILL GET! ** ** My pleasure. */
#define M 002354l#define A 000644l#define G 000132l#define I 000322l#define C 000374l
TVF / RIT 20195 CS243: More About CPP
obfus2_full.c (3/4)#define a ;#define b for#define c ++#define d %#define e int#define f ,#define g #define h 011#define i =#define j {#define k )#define l '\n'#define m main#define n <#define o }#define p >#define q &&#define r (#define s ||#define t ?#define u putchar#define v void#define w '*'#define x :#define y ' '#define _ /#define C_O_O_L return
TVF / RIT 20195 CS243: More About CPP
obfus2_full.c (4/4)
e u r e k a
e m r v k j j j j j j j j j j j j j j j j j j j j j j j j e z a b r z i M _ A _ G _ I _ C a z n G a u r z d h + z _ h p M _ A q z d h + z _ h n M _ G q z _ h n z d h + M _ I q z _ h p z d h g M _ C t w x y k f z d h g h + 1 s u r l k f z c k a u r l k a j j j j j j j j j j j C_O_O_L M _ A _ G _ I _ C a o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
TVF / RIT 20195 CS243: More About CPP
Operation
$ ./obfus2 * *** ***** ******* ****************** ******* ***** *** *