0% found this document useful (0 votes)
76 views36 pages

11 - The Preprocessor

The preprocessor is the first stage of compilation that performs text substitution and conditional compilation. It includes header files, expands macros, and removes comments. Common preprocessing directives are #include to insert header files, #define for macros and constants, and #if for conditional compilation like debugging code. The preprocessor outputs preprocessed code that is passed to the compiler without understanding C language rules.

Uploaded by

Ido Akov
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
76 views36 pages

11 - The Preprocessor

The preprocessor is the first stage of compilation that performs text substitution and conditional compilation. It includes header files, expands macros, and removes comments. Common preprocessing directives are #include to insert header files, #define for macros and constants, and #if for conditional compilation like debugging code. The preprocessor outputs preprocessed code that is passed to the compiler without understanding C language rules.

Uploaded by

Ido Akov
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 36

The Preprocessor

1
Compilation process in C

Contains 3 different stages:


1. Preprocessor
2. Compiler
3. Linker

Each one is program which process


the output of the previous one

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

• Compilation is the processing of source code files (.c, .cc, or .cpp)


and the creation of an 'object' files (*.o)
Compiler
• You can’t run object files
• The compiler produces the machine language instructions

• Linking creates a single executable file from multiple object files


• linker will complain about undefined functions. If the compiler
could not find the definition for a particular function, it would just
assume that the function was defined in another file.
• The linker may look at multiple files and try to find references for
the functions that weren't mentioned
Linker
3
gcc

• GNU software

GNU: an extensive collection of computer software,


Unix-like design. (but acronym: GNU's Not Unix!)

• gcc is called “compiler”, though it also runs the


preprocessing and (optionally) linking

• Example: run in the shell: gcc hello.c -o hello

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

A single-pass program that:


1. Includes header files
2. Expands macros
3. Controls conditional compilation
4. Removes comments

Outputs –
6 a code ready for the compiler to work on
Preprocessor

We can test what the preprocessor does:

> gcc –E hello.c

will print the C code after running the


preprocessing stage

7
Common Pre-processing Directives

❑ #include

❑ #define

❑ #if ... #else ... #endif

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

Note that “File.h” is not the same as


“file.h” (Win, Linux)
11
Header files
Header file contains
1. Definitions of data types (typedef,
structs)
2. Declarations of functions & constants that
are shared by multiple modules

#include allows several modules to share


the same set of definitions/declarations

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;

is equivalent (after the preprocessing) to:


int x = 1;

15
#define with arguments - MACRO

#define SQUARE(x) x*x
b = SQUARE (a);

is the same as

b = a*a;

16
#define - caveat

#define SQUARE(x) x*x After preprocessing:


b = SQUARE(a+1); A. b = a^2 +2a +1
B. b = 2a+1
C. b = a^2

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;

We actually get the following:


b = a+1*a+1; // b = 2*a + 1
c = a+a*5; // c = 6*a
18
#define - cautions

#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;

• Functions – inline functions (C99, C++,


will be discussed later on)

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

Example of using conditional compilation


assert.h
#include <assert.h>
// Sqrt(x): compute square root of x
// Assumption: x is non-negative
double sqrt(double x )
{
   assert(x >= 0);  // aborts if x < 0

}
If the program violates the condition, then the
program will abort and print:
assertion "x >= 0" failed: file "Sqrt.c",
line 7 <exception>
25
assert.h

The assertion allows to catch the event


in debug mode, during runtime,
(specifically, not compile-time).

26
assert.h

• Important coding practice

• Declare implicit assumptions

• Checked during debug stage.

The following examples include more preprocessing


directives (#, ##) – read at home about this syntax
27
assert.h
// procedure that prints error message // to disabl
e the printing define the macro NDEBUG
// before the <assert.h> inclusion
void __assert(char* file, int line, char* test);

#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

void __assert(char* file, int line, char* test);

#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

#define NDEBUG Debug/Test


mode vs
#include <assert.h> Release mode

int main()
{
int i = foo();
assert(i>=0);
return 0;
}

33
Defining NDEBUG using the compiler

>> gcc my_program.c –DNDEBUG –o my_exe

This is equivalent for adding at the beginning of the


file, the definition:
#define NDEBUG

34
Preprocessor – summary

❑ Text processing program

❑ Does not know C language rules

❑ Operates before compilation, output passed

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

You might also like