11 - The Preprocessor
11 - The Preprocessor
11 - The Preprocessor
1
Compilation process in C
text opcodes
2
Code to executable in C
• The C Preprocessor is not a part of the compiler
• separate step in the compilation process Preprocessor
• preprocessor is just a text substitution tool
• GNU software
4
Compilation process in C
Files with C code has the suffix .c or .h
hello.c
tmpXQ.i
Preprocessor Compiler
)C code(
stdio.h
hello.o
:Executable object(
linker
Hello )file
5
Preprocessor
Outputs –
6 a code ready for the compiler to work on
Preprocessor
7
Common Pre-processing Directives
❑ #include
❑ #define
8
#include
9
#include directive
#include "foo.h"
Includes the file ‘foo.h’, starts searching from
the same directory as the current file (the
one that contains the #include directive)
#include <stdio.h>
Includes the file ‘stdio.h’, starts searching from
the standard library directory (part of gcc
installation)
10
#include directive
#include “file”
=
Copy & paste the content of “file” in
this location and continue with pre-
processing
12
Modules & Header files
Shape.h
// declaration
int area(int x1, int y1, int x2,
Complex.c int y2);
...
MyProg.c Shape.c
#include “Shape.h" #include <math.h>
int main() // implementation
{ int area(int x1,int y1,int x2, int y2)
// usage
area(2,3,5,6); {
} ...
}
13
#define
14
#define directive
#define FOO 1
int x = FOO;
15
#define with arguments - MACRO
#define SQUARE(x) x*x
b = SQUARE (a);
is the same as
b = a*a;
16
#define - caveat
A B C
0
17
#define - cautions
#define SQUARE(x) x*x
#define PLUS(x) x+x
b = SQUARE(a+1);
c = PLUS(a)*5;
#define SQUARE(x) x*x
#define PLUS(x) x+x
b = SQUARE(a+1);
c = PLUS(a)*5;
Solution:
#define SQUARE(x) ((x)*(x))
#define PLUS(x) ((x)+(x))
19
#define
Multi-line:
All preprocessor directive effect one line (not c statement).
To insert a line-break, use “\”:
BAD:
#define x (5 +
5)
GOOD:
#define x (5 + \
5)
// x == 10 !
20
Alternative to macros
• Constants
enum { FOO = 1 };
or
const int FOO = 1;
21
#if
22
#if directive: conditional compilation
#define DEBUG
#ifdef DEBUG
// compiles only when DEBUG exists (defined)
printf("X = %d\n", X);
#endif
23
Debugging - assert
26
assert.h
#ifdef NDEBUG
#define assert(e) ((void)0)
#else
#define assert(e) \
((e) ? ((void)0) : \
__assert(__FILE__, __LINE__, #e))
#endif
28
Preprocessor: step 1
Preprocessor
#include <assert.h> copy-paste
int main()
{
int i = foo();
assert(i>=0);
return 0;
}
29
Preprocessor: step 2
void __assert(char* file, int line, char* test);
#ifdef NDEBUG Preprocessor
#define assert(e) ((void)0) cut-out
#else
#define assert(e) \
((e) ? ((void)0) : \
__assert(__FILE__, __LINE__, #e))
#endif
int main()
{
i = foo();
assert(i>=0);
return 0;
}
30
Preprocessor: step 3
#define assert(e) \ Preprocessor
copy-paste
((e) ? ((void)0) : \
__assert(__FILE__, __LINE__, #e))
int main()
{
int i = foo();
assert(i>=0);
return 0;
}
31
Preprocessor: output
Without
void __assert(char* file, int line, char* test); this the
code will
not
int main() compile
{ in the
int i = foo(); next
((i>=0) ? ((void)0) : \ stage
__assert(__FILE__, __LINE__, #e))
return 0;
}
32
Preprocessor: step 1
int main()
{
int i = foo();
assert(i>=0);
return 0;
}
33
Defining NDEBUG using the compiler
34
Preprocessor – summary
to compiler
❑ Can do “copy and paste”, or, “cut”
35
Preprocessor – summary
#include
➢ pastes the included file to current file (.h by convention)
➢ usually contains forward declarations and type definitions
#define
➢ copy-pastes the macro body where macro name appears
➢ used for constants, or simple "functions"
#if
➢ if condition is not fulfilled, “cut” the code
➢ conditional compilation (e.g. debugging code)
36