Preprocessor Statements R. Inkulu http://www.iitg.ac.in/rinkulu/ - - PowerPoint PPT Presentation

preprocessor statements r inkulu http iitg ac in rinkulu
SMART_READER_LITE
LIVE PREVIEW

Preprocessor Statements R. Inkulu http://www.iitg.ac.in/rinkulu/ - - PowerPoint PPT Presentation

Preprocessor Statements R. Inkulu http://www.iitg.ac.in/rinkulu/ (Preprocessor Statements) 1 / 18 File inclusion abc.h : abc.c after compiler int func1(float); pre-processing: float func2(double, double); int func1(float); . . . float


slide-1
SLIDE 1

Preprocessor Statements

  • R. Inkulu

http://www.iitg.ac.in/rinkulu/

(Preprocessor Statements) 1 / 18

slide-2
SLIDE 2

File inclusion

abc.h: int func1(float); float func2(double, double); . . . abc.c: #include ”abc.h” int func1(float) { . . . } float func2(double, double) { . . . } . . . main.c: #include ”abc.h” int main(void) { int k = func1(35.678); } abc.c after compiler pre-processing: int func1(float); float func2(double, double); . . . int func1(float) { . . . } float func2(double, double) { . . . } . . . main.c after compiler pre-processing: int func1(float); float func2(double, double); . . . int main(void) { int k = func1(35.678); }

(Preprocessor Statements) 2 / 18

slide-3
SLIDE 3

Macro Substitution

. . . #define ARRAYSIZE 512 . . . int func(double) { . . . int buffer1[ARRAYSIZE]; . . . double buffer2[ARRAYSIZE]; . . . char buffer3[ARRAYSIZE]; . . . } int func(double) { . . . int buffer1[512]; . . . double buffer2[512]; . . . char buffer3[512]; . . . }

  • Errors due to duplication can be eliminated

(Preprocessor Statements) 3 / 18

slide-4
SLIDE 4

Macro with arguments: parenthesization issue

. . . #define SQUARE(x) x*x . . . int func(void) { . . . double f = SQUARE(23.89); . . . int i = 2, j = 3; int k = SQUARE(i+j); . . . } int func(void) { . . . double f = 23.89*23.89; . . . int i = 2, j = 3; int k = i+j*i+j; . . . }

  • precedence issue with the second substitution

(Preprocessor Statements) 4 / 18

slide-5
SLIDE 5

Macro with arguments: local fix

. . . #define SQUARE(x) x*x . . . int func(void) { . . . double f = SQUARE((23.89)); . . . int i = 2, j = 3; int k = SQUARE((i+j)); . . . } int func(void) { . . . double f = (23.89)*(23.89); . . . int i = 2, j = 3; int k = (i+j)*(i+j); . . . }

(Preprocessor Statements) 5 / 18

slide-6
SLIDE 6

Macro with arguments: global fix

. . . #define SQUARE(x) ((x)*(x)) . . . int func(void) { . . . double f = SQUARE(23.89); . . . int i = 2, j = 3; int k = SQUARE(i+j)/7; . . . } int func(void) { . . . double f = ((23.89)*(23.89)); . . . int i = 2, j = 3; int k = ((i+j)*(i+j))/7; . . . }

(Preprocessor Statements) 6 / 18

slide-7
SLIDE 7

Macro with arguments: unavoidable side effect

. . . #define SQUARE(x) ((x)*(x)) . . . int func(void) { . . . double f = SQUARE(23.89); . . . int i = 2, j = 3; int k = SQUARE(++i); assert (i == 3); . . . } int func(void) { . . . double f = ((23.89)*(23.89)); . . . int i = 2, j = 3; int k = ((++i)*(++i)); assert (i == 3); . . . }

  • in the second substitution, i is incremented twice → could be an

unexpected result

(Preprocessor Statements) 7 / 18

slide-8
SLIDE 8

if statement and a macro

incorrect code: semantics changed . . . #define SWAP(x, y, w) w=x; x=y; y=w; . . . int func(void) { . . . int i=3,j=8,t=-1; if (i > j) SWAP(i, j, t); . . . printf(”%d,%d”, i, j); . . . } int func(void) { . . . int i=3,j=8,t=-1; if (i > j) t=i; i=j; j=t;; . . . printf(”%d,%d”, i, j); //prints 8, -1 ! . . . }

(Preprocessor Statements) 8 / 18

slide-9
SLIDE 9

if-else statement and a macro: poor fix

incorrect code: leads to compile-time error . . . #define SWAP(x, y, w) {w=x; x=y; y=w;} . . . void func2(void) { . . . } int func(void) { . . . int i=3,j=8,t=-1; if (i > j) SWAP(i, j, t); else func2(); . . . } int func(void) { . . . int i=3,j=8,t=-1; if (i > j) {t=i; i=j; j=t;}; else func2(); . . . }

  • semicolon after SWAP(i, j) is the reason for havoc

(Preprocessor Statements) 9 / 18

slide-10
SLIDE 10

if-else statement and a macro: right fix

. . . #define SWAP(x, y, w) do {w=x; x=y; y=w;} while (0) . . . void func2(void) { . . . } int func(void) { . . . int i=3,j=8,t=-1; if (i > j) SWAP(i, j, t); else func2(); . . . } int func(void) { . . . int i=3,j=8,t=-1; if (i > j) do {t=i; i=j; j=t;} while(0); else func2(); . . . }

(Preprocessor Statements) 10 / 18

slide-11
SLIDE 11

Quoted string macro

. . . #define DPRINT(expr) printf(”debug start ” #expr ”=%d”, expr) . . . int func(void) { . . . int x = 8, y = 4; DPRINT(x/y); . . . } int func(void) { . . . int x = 8, y = 4; printf(”debug start ” ”x/y” ”= %d”, x/y); . . . } int func(void) { . . . int x = 8, y = 4; printf(”debug start x/y=%d”, x/y); . . . }

(Preprocessor Statements) 11 / 18

slide-12
SLIDE 12

Macros with arguments vs Functions

adv with macros:

  • no func invocation cost in the runtime, hence faster
  • useful in making small functions inline

disadv with macros:

  • size of object file increases
  • no type checking of parameters
  • side-effects

multiple prefix/postfix operations per substitution precedence issues using macro between if-else keywords

  • difficult to debug while having breakpoints within a macro

(Preprocessor Statements) 12 / 18

slide-13
SLIDE 13

Few popular macros

  • getchar
  • putchar
  • va start
  • va arg
  • va end
  • DATE

date of compilation

  • TIME

time of compilation

  • LINE

line number

  • FILE

name of file

(Preprocessor Statements) 13 / 18

slide-14
SLIDE 14

Duplicate inclusion due to multiple header file inclusions

abc1.h: typedef struct { . . . } Home; extern int globalVar; . . . abc2.h: #include ”abc1.h” . . . Home func2(double, double); . . . abc3.h: #include ”abc1.h” . . . void func3(Home); . . . abc4.c: #include ”abc2.h” #include ”abc3.h” int main(void) { . . . Home home = func2(35.67, 89.05); . . . func3(home); . . . }

(Preprocessor Statements) 14 / 18

slide-15
SLIDE 15

Conditional compilation

abc1.h: #ifndef FILEABC1 #define FILEABC1 typedef struct { . . . } Home; extern int globalVar; . . . #endif abc2.h: #include ”abc1.h” . . . Home func2(double, double); . . . abc3.h: #include ”abc1.h” . . . void func3(Home); abc4.c: #include ”abc2.h” #include ”abc3.h” int main(void) { . . . Home home = func2(35.67, 89.05); func3(home); . . . }

(Preprocessor Statements) 15 / 18

slide-16
SLIDE 16

Conditional compilation (cont)

. . . #if SYSTEMTYPE == LINUX . . . #elif SYSTEMTYPE == SOLARIS . . . #elif SYSSTEMTYPE == WINDOWS . . . #else . . . #endif . . .

  • If the system is LINUX, preprocessor gives the code block listed

after LINUX test and before SOLARIS test to compiling phase → hence, the term conditional compilation

(Preprocessor Statements) 16 / 18

slide-17
SLIDE 17

Undefining a #define

#define ARRAYSIZE 20 . . . #undef ARRAYSIZE #define ARRAYSIZE 30 . . . #undef getchar int getchar(void) { . . . } . . .

(Preprocessor Statements) 17 / 18

slide-18
SLIDE 18

Pragma Directives

. . . #pragma setlocale(”dutch”) . . . . . . #pragma optimize(on) . . . #pragma optimize(off) . . .

  • pragma statement gives additional information to compiler

(Preprocessor Statements) 18 / 18