Top Banner
1 • Preprocessor How it works File Inclusion: #include Macro Definition: #define Predefined macros __LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation – #if-#endif – #if-#elif-#else-#endif – #ifdef-#endif – #ifndef-#endif – #error Today’s Material
31

1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

Jan 05, 2016

Download

Documents

Patrick Fowler
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

1

• Preprocessor– How it works

• File Inclusion: #include

• Macro Definition: #define

• Predefined macros– __LINE__, __FILE__, __DATE__, __TIME__

• Conditional Compilation– #if-#endif– #if-#elif-#else-#endif– #ifdef-#endif– #ifndef-#endif– #error

Today’s Material

Page 2: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

2

• Commands that begin with # character are called preprocessor directives– Recall #include, #define

• The following diagram shows the preprocessor’s role in the compilation process

Preprocessor

prog.i

COMPILER

prog.c

PREPROCESSOR (cpp)

Modified C program [text file]

Source code [text file]

prog.o Object Code [binary file]

Page 3: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

3

• Input to the preprocessor is a C program containing directives– Preprocessor executes these directives

(commands) and removes them (including comments)

• The output of the preprocessor is an edited version of the C program containing no preprocessor directives– The output of the preprocessor directly goes into

the compiler, which generates the C object code– In fact, the compiler first generates an assembly

code, which is fed into an assembler, which generates the object code

Preprocessor: How it works

Page 4: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

4

• Preprocessor directives fall in the following categories

1. File inclusion– #include

2. Macro Definition– #define

3. Conditional Compilation– #if, #ifdef, #ifndef, #elif, #else, #endif

4. Rest of the Directives– #error, #line, #pragma– Specialized and less often used

Preprocessor Directives

Page 5: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

5

• Directives always start with # char– # char need not be at the beginning of a line, as

long as only white space precedes it– #include …– #include …

• Any number of spaces and horizontal tab chars may separate the tokens in a directive– #include …– # include …– #include …– # include …

Preprocessor Directive Format(1)

Page 6: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

6

• Directives always ends at the first new-line char unless explicitly continued

Preprocessor Directive Format(2)

#define A 2*3 /* ends at the end of the line */

#define B 2* \ /* continues at the next line */3* \ /* continues at the next line */

4 /* ends at the end of the line */

/* Same as #define B 2*3*4 *//* Backslash (\) is the continuation character */

Page 7: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

7

• Tells the preprocessor to open a particular file, and “include” its contents as part of the file being processed

#include Directive(1)

#include <stdio.h>main(){ printf(“Hello World\n”);}

• Instructs the preprocessor to open file named stdio.h (located in /usr/include/stdio.h), and bring its contents into the program

% cpp –o hello.i hello.c/* To see what’s included from stdio.h */

Page 8: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

8

#include Directive(2)#include <defs.h>/* Search defs.h in standard include directories * i.e., /usr/include, and in any other directory * specified by –I compiler flag * Example: */

% gcc –I/root den.c/* -I/root means that in addition to searching * /usr/include, we want the compiler to also search * /root for any files included with <>, */

#include “defs.h”/* means: Search defs.h in standard include * directories (/usr/include) AND the current * directory */

Page 9: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

9

• #define directive defines a macro– a name that represents something else, typically

a constant of some kind

• When the macro is used in the program, the preprocessor expands the macro, replacing it with its definition– This replacement is literal or verbatim

#define Directive(1)

#define N 100int A[N];/* becomes * int A[100]; * after preprocessor processes the C program */

Page 10: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

10

#define Example/* Some comment */#define FREEZING_POINT 32#define SCALING_FACTOR 1.8

main(){ float fahrenheit, celsius;

fahrenheit = 75; celsius = (fahrenheit-FREEZING_POINT)/SCALING_FACTOR;}

blankblankblank

main(){ float fahrenheit, celsius;

fahrenheit = 75; celsius = (fahrenheit-32)/1.8;}

Macros Expanded

Comment removed

Macro definitions removed

Page 11: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

11

• Macros are expanded literally

#define: Caveats

#define N =100int A[N]; expanded to int A[=100];

#define N 100;int A[N]; expanded to int A[100;];

Page 12: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

12

• Simple macros are primarily used to define constants

#define: Primary Usage

#define TRUE 1#define FALSE 0#define PI 3.14159#define DEBUG /* It is OK for the replacement list to be empty */

Page 13: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

13

#define: Advantages

• Using #define to create names for constants has several significant advantages– Makes programs easier to read– Makes programs easier to modify– Helps avoid inconsistencies and typos:

• It is difficult to consistently type 3.14159

Page 14: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

14

Parameterized Macros

• There must be NO space between macro name and the left parenthesis– If there is a space, the preprocessor assumes

that (..) is part of the replacement list

• x1, x2, x3, …, xn are identifiers – Called the macro’s parameters– Parameters may appear as many times as

desired in the replacement list

#define identifier(x1,x2,x3,..,xn) replacement-list

Page 15: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

15

Macro Example#define MAX(x,y) x>y?x:y#define MULT(x,y) x*y

main(){ int i, a=2, b=3; i = MAX(a,b); /* Expanded to i = a>b?a:b; */ i = MULT(a,b); /* Expanded to i = a*b; */ i = MULT(a+2, b+3); /* Expanded to i = a+2*b+3; */ /* This last MULT will produce incorrect result * To fix the problem, you need to parenthesize * the macro as follows: */} /* end-main */

#define MULT(a,b) ((a)*(b))i = MULT(a+2, b+3); /* Expanded to */i = ((a+2)*(b+3)); /* Correct now */

Page 16: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

16

• A macro definition can extend to several lines– Must continue the lines by ‘\’ char

Macros (More)

#define SAMPLE(x,y,z,t) (\ (x)+\ (y)+\ (z)+\ (t)\ )

• A macro definition can make use of other macros defined earlier

#define MAX(a,b) ((a)>(b)?(a):(b))#define MAX3(x,y,z) (MAX(x, MAX(y,z)))

Page 17: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

17

• A parameterized macro can have an empty parameter list

Macros (More)

#define getchar() fgetc(stdin)

/* This is how getchar is defined in <stdio.h> * () is really not needed, but makes getchar * look like a function. So it is used. */

Page 18: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

18

Macros: Important Note

• A parameterized macro is NOT a function

• When the preprocessor encounters a macro, it simply expands it within the source code

• Thus the compiler is NOT even aware that the code has been generated by a macro expansion

Page 19: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

19

Advantages of Macros over Functions

1. Program is slightly faster– No overhead of a function call and function

return

2. Macro parameters are generic– Macro parameters do not have types– So we can use the same macro with int, float,

double etc. arguments. E.g., MAX macro defined earlier

Page 20: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

20

Disadvantages of Macros over Functions

1. Compiled code will be larger• Since macros are expanded within the source

code, the size of the code gets big

2. Arguments are not type-checked• With functions, the compiler type-checks the

arguments and warns you if there is an error• With macros, this type-checking is NOT possible

3. Macros may evaluate their arguments more than once

n = MAX(i++, j); /* Expanded to */n = (i++ > j)?(i++):(j);/* If i is greater than j, i will be incremented twice, * and n gets the wrong value *//* If MAX was a function, n would get the bigger of i &j and * i would be incremented once. This is due to the fact that * function arguments are evaluated before the function call */

Page 21: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

21

Macro Scope

• Macro definitions remain in effect until the end of the file in which they appear

• Macros may be undefined by #undef directive– #undef identifier– #undef is typically used to remove the existing

definition of a macro, so that it can be redefined

Page 22: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

22

Predefined Macros(1)• Predefined macros

__LINE__ : Line # of the file being compiled__FILE__ : Name of the file being compiled__DATE__ : Date of compilation “Mmm dd yyyy”__TIME__ : Time of compilation “hh:mm:ss”

printf(This software is compiled on %s at %s\n”, __DATE__, _TIME__);

Page 23: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

23

Predefined Macros(2)• We can use _LINE__ and _FILE__ macros to

locate errors#define CHECK_ZERO(divisor)\ if (divisor==0) {\ printf(“**Attempt to divide by zero on line ” \ “%d of file %s**\n”, __LINE__, __FILE__); \ exit(1); /* Terminate the program */ \ } /* end-if */

• Let’s use this macro in our program

CHECK_ZERO(j);k = i/j;

/* if j is zero, CHECK_ZERO will print an error * message and terminate the program */

Page 24: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

24

assert macro• C Library provides a similar macro named

assert– Need to include <assert.h>#include <assert.h>

int i, k;i = 0;assert(i!=0);k = 20/i;

• Assert is defined as follows

#define assert(c) \ if (c){ \ printf(“Assertion failed %s\n”, #c); \ } /* end-if */

/* #c makes c a string */

Page 25: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

25

Conditional Compilation• C preprocessor recognizes a number of

directives that support conditional compilation– The inclusion or exclusion of a section of a

program text depending on the outcome of a test performed by the preprocessor

• Conditional Compilation Directives are– #if-#endif– #if-#else-#endif– #if-#elif-#else-#endif– #ifdef-#endif– #ifndef-#endif

Page 26: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

26

#if-#endif• Suppose there is a section of code that you

want to have compiled based on a condition• Classical example is the debug code that

you insert in your programs– You want to compile your program with the

debug code to see the debug output when debugging

– When the program is all debugged & you do not want to see the debug output anymore, you simply want to avoid compiling that section of the code rather than remove it

– Here is how you can achieve it

Page 27: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

27

#if-#endif#define DEBUG 1 /* Simply set DEBUG to 0 if you don’t * want to see the debug output */#if DEBUG

printf(“i: %d\n”, i); printf(“j: %d\n”, j);#endif

• In general, #if directive has the form

#if constant-expression .. .. ..#endif

Page 28: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

28

#if-#elif-#else-#endif• #if, #endif can be nested just like ordinary if

statements using #elif, #else directives

#define DEBUG 1

#if DEBUG == 1 .. ..#else .. ..#endif

#define DEBUG 1

#if DEBUG == 1 .. ..#elif DEBUG == 2 .. ..#else .. ..#endif

Page 29: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

29

defined operator• Defined operator allows you to test whether

a macro is defined yet– You can use this operator in #if, #elif directives

#if defined(WINDOWS) int g = 3; ..#elif defined(LINUX) int g = 2; ..#elif defined(SOLARIS) int g = 4; ..#else .. ..#endif

• Example: – You want to initiate

a variable/declare a function differently depending on the OS

Page 30: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

30

#ifdef, #ifndef• Instead of using defined operator, there is a

shorter way to write the same code using #ifdef & #ifndef

#ifdef WINDOWS int g = 3; ..#endif

#ifdef LINUX int g = 2; ..#endif

#ifdef SOLARIS int g = 4; ..#endif

• Using #ifndef you want the code to get compiled when the macro is NOT defined

Page 31: 1 Preprocessor –How it works File Inclusion: #include Macro Definition: #define Predefined macros –__LINE__, __FILE__, __DATE__, __TIME__ Conditional Compilation.

31

Other Directives• #error message

– When the preprocessor encounters an #error directive, it prints the error “message”

#if INT_MAX < 100000#error int type is too small!#endif

• #error directive is often found in the #else part of an #if-#elif-#endif series

#if defined(WINDOWS) ..#elif define(LINUX) ..#else#error No OS specified#endif