Title: CS 2130
1CS 2130
- Presentation 05
- C Preprocessor
2C Preprocessor Provides
- Inclusion of header files.
- Macro expansion.
- You can define macros, which are abbreviations
for arbitrary fragments of C code, and then the C
preprocessor will replace the macros with their
definitions throughout the program. - Conditional compilation.
- Include or exclude parts of the program according
to various conditions. - Line control.
3Inclusion of Header Files
- Typical "Includes"
- include ltstdio.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
Header files typically contain Definitions Decla
rations Function Prototypes
4Back to Hello World
- include ltstdio.hgt
- include ltstdlib.hgt
- int main(void)
-
- printf(Hello, World!\n)
- return EXIT_SUCCESS
OK?
5Doesnt printf return something?
- printf(3) returns number of characters
transferred - Therefore
- gt 0 Success
- lt 0 Failure
- Probably not worthwhile to check return value
- Could do this
- (void)printf(
- Which means ignore return value
- BUT THIS COULD BE A REAL BAD IDEA
6Some simple streams
- By default we are supplied the following streams
- stdin Keyboard
- stdout Screen
- stderr Screen
7So we could do...
- if(printf() lt 0)
-
- fprintf(stderr,printf failed\n)
- / perhaps exit here? /
-
One slight problem!
8So we could do...
- if(printf() lt 0)
-
- (void)fprintf(stderr,printf failed\n)
- / perhaps exit here? /
-
Does it make sense to use (void) in front of
fprintf?
9Three Exceptions
- All function return values must be checked except
- (void)fprintf(stderr,
- (void)fflush(stderr)
- exit(EXIT_FAILURE)
- WITHOUT FAIL!!!
10Whenever you call a function, especially a system
call or a library function, ask yourself
- What does the return value signify?
- What will happen if this function returns an
error code and I ignore it? - How can I make this code foolproof?
11Getting out right now!
- exit(EXIT_FAILURE)
- Why not just
- return EXIT_FAILURE
12Macro Processing
- Would like a simple way of performing
- if(printf() lt 0)
-
- (void)fprintf(stderr,printf failed\n)
- / perhaps exit here? /
-
- Macro Processing could be the answer but first...
13When Things Happen
- Key focus of CS 2130 is understanding when things
happen - During Translation (Compilation)
- During Execution
Sidebar
14Translation (Compilation)
- 0. Preprocessing
- 1. Lexical Analysis (Scanning)
- Remove Comments
- Find Keywords (Reserved Words)
- 2. Syntax Analysis
- Check for structural correctness
- 3. Semantic Analysis
- Concerned with meaning
- 4. Code Generation
- 5. Optimization
- Time
- Space
- Global vs. Peephole
Sidebar
15Macro Processing
- When does it occur?
- Before step 1. Lexical Analysis
- Thus 0. Macro Processing
- What is it?
- Text substitution
- Following precise rules
- In C, Macro Processing is done by the C
Preprocessor - Takes c source file
- Does macro processing
- Passes results to C Compiler
16Macro Processing?
- define ONE 1
- x y ONE
- becomes
- x y 1
- return DONE
- remains unchanged
17C Preprocessor in Action!
- /usr/lib/cpp
- gcc -E
- Both run c preprocessor sending output to stdout
- /usr/lib/cpp yourprogram.c gt someFile.txt
- gcc -E yourprogram.c gt someFile.txt
18Macro Examples
- include ltstdio.hgt
- include defs.h
- Looks in /usr/include for stdio.h inserts
contents into source file - Looks for defs.h in local directory and inserts
contents into source file
19Macro Examples
- define EXIT_SUCCESS 0
- Note Not a constant
- const int foo 42
- Macro processing uses a symbol table technique
20Symbol Table
- Used commonly in any translation operation
- Symbol Name Symbol Attributes
- foo type, value, address, scope,
- lifetime, constant
21Example
- define EXIT_SUCCESS 0
- return EXIT_SUCCESS
22Example
- define EXIT_SUCCESS 0
- return 0
23Why?
- EXIT_SUCCESS
- Meaningful self-documentation
24Shooting oneself in the foot
- define ONE 1
- define TWO ONE ONE
- int x ONE, y TWO
- becomes
- int x 1, y ONE ONE
- becomes
- int x 1, y 1 1
25Efficiency
- Clearly
- y 2
- is more efficient than
- y 1 1
26WRONG!
27When do things happen?
- Translation
- static stuff
- Execution
- dynamic stuff
Preprocessor Here
Imagine that you are hand translating the C
program into assembly language. What do you know
now? What will only be know when the program is
running???
28More foot perforating
- int z TWO TWO
- becomes
- int z 1 1 1 1
- Probably not what was intended!!!
- Parentheses are your friend
- define TWO (ONE ONE)
- define ONE (1) / OVERKILL /
29Parentheses
- ANSI standard guarantees 32 levels of parentheses
nesting - enough to satisfy Mr. Scheme Kurt Eiselt
30More shootin
- define SQUARE(X) (X X)
- int z SQUARE(2)
- int z SQUARE(x y)
- Fix
- define SQUARE(X) ((X) (X))
OK?
31NOT!
- z SQUARE(x)
- becomes
- z ((x) (x))
- Whats the correct answer?
- z x2
- z (x 1)2
- z x (x 1)
- z (x 1) (x 2)
32NOT!
- z SQUARE(x)
- becomes
- z ((x) (x))
- Whats the correct answer?
- z x2 / maybe /
- z (x 1)2 / probably not /
- z x (x 1) / maybe /
- z (x 1) (x 2) / Probably not /
33Another Possibility
- Make SQUARE a function
- int square(int x)
-
- return x x
-
- Now its a win!
- z square(x)
- z square(xy)
- z square(x)
- All work properly
- Or is it? Any downside?
34What happens?
- / Macro /
- SQUARE(x)
- .
- .
- .
- SQUARE(x)
- .
- .
- .
- SQUARE(x)
-
- / Function /
- square(x)
- .
- .
- .
- square(x)
- .
- .
- .
- square(x)
35What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
36What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
37What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
38What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
39What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
40What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
41What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
42What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
- / Function /
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- pass parameter(s)
- call function
- .
- square function
- return
43Macros vs. Functions
- Macros
- Text substitution at Translation (compile) time
- May have problems e.g. square(x)
- Will work with different types due to operator
overloading - floats, doubles, ints,
- Difficult to implement if complex
- Macro optimizes for speed. Why?
- Functions
- Separate piece of code
- Overhead of passing arguments and returning
results via stack - Fixes ambiguity problems e.g. square(x y)
or(x) - Function optimizes for space. Why?
44Macros vs. Functions
- If the goal is not clearly optimization for speed
or time but rather somewhere in-between its
difficult to know exactly which choice is
correct. - In any event Dont try and outwit the compiler!
- A better algorithm is more of an improvement that
trying to write tricky code!!!
45Inline
- Can write
- inline int
- square(int x)
-
- return xx
-
- Now square(a) will work correctly with macro
like performance. - Why use inline?
- Compiler will make decision for you if inline
omitted - gcc -finline-functions
46Questions?
47Pop Quiz
- Write a macro to automatically check for return
values from printf
48Recall
- printf("some stuff d f", i, x)
- Problem We're ignoring the return value which
could indicate a problem
49We should write...
- if(printf("some stuff d f", i, x)lt0)
-
- (void)fprintf(stderr,"Yikes!!!")
- exit(EXIT_FAILURE)
-
- Which, of course, is a pain in the neck!
50First Approach
- define PRINTF( stuff ) if(printf stuff lt0) \
- \
- (void)fprintf(stderr,"Yikes!!!") \
- exit(EXIT_FAILURE) \
-
- and we would use it like this
- PRINTF( "some stuff d f", i, x )
- OK?
51Not exactly...
- define PRINTF( stuff ) if(printf stuff lt0) \
- \
- (void)fprintf(stderr,"Yikes!!!") \
- exit(EXIT_FAILURE) \
-
- This is the fix
- PRINTF( ( "some stuff d f", i, x ) )
-
52Questions?
53Conditional Compilation
- if
- endif
- else
- elif
- ifdef name
- note equivalent to if defined (name)
- endif
- ifndef
- note equivalent to if ! defined (name)
- endif
54Examples
- if X 1
- ...
- else / X ! 1 /
- if X 2
- ...
- else / X ! 2 /
- ...
- endif / X ! 2 /
- endif / X ! 1 /
- if X 1
- ...
- elif X 2
- ...
- else / X ! 2 and X ! 1/
- ...
- endif / X ! 2 and X ! 1/
-
55Keeping Deleted Code
- if 0
- deleted code here
- endif
56Warning
- Programmers often wish they could test the size
of a variable or data type in if', but this
does not work. The preprocessor does not
understand sizeof, or typedef names, or even the
type keywords such as int.)
57More?
- http//gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.htm
l
58Questions?
59(No Transcript)