Title: CS 2130
1CS 2130
- Presentation 05
- C Preprocessor
2Typical "Includes"
- include ltstdio.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
3Back to Hello World
- include ltstdio.hgt
- include ltstdlib.hgt
- int main(void)
-
- printf(Hello, World!\n)
- return EXIT_SUCCESS
OK?
4Doesnt 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
5Some simple streams
- By default we are supplied the following streams
- stdin Keyboard
- stdout Screen
- stderr Screen
6So we could do...
- if(printf() lt 0)
-
- fprintf(stderr,printf failed\n)
- / perhaps exit here? /
-
One slight problem!
7So 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?
8Three Exceptions
- All function return values must be checked except
- (void)fprintf(stderr,
- (void)fflush(stderr)
- exit(EXIT_FAILURE)
- WITHOUT FAIL!!!
9Whenever 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?
10Getting out right now!
- exit(EXIT_FAILURE)
- Why not just
- return EXIT_FAILURE
11Macro 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...
12When Things Happen
- Key focus of CS 2130 is understanding when things
happen - During Translation (Compilation)
- During Execution
Sidebar
13Translation (Compilation)
- 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
14Translation (Compilation)
- 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
Front End (Analysis)
Sidebar
Back End (Synthesis)
15Translation (Compilation)
- 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
Parsing
16Macro 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
17Macro Processing?
- define ONE 1
- x y ONE
- becomes
- x y 1
- return DONE
- remains unchanged
18C 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
19Macro 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
20Macro Examples
- define EXIT_SUCCESS 0
- Note Not a constant
- const int foo 42
- Macro processing uses a symbol table technique
21Symbol Table
- Used commonly in any translation operation
- Symbol Name Symbol Attributes
- foo type, value, address, scope,
- lifetime, constant
22Example
- define EXIT_SUCCESS 0
- return EXIT_SUCCESS
23Example
- define EXIT_SUCCESS 0
- return 0
24Why?
- EXIT_SUCCESS
- Meaningful self-documentation
25Shooting 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
26Efficiency
- Clearly
- y 2
- is more efficient than
- y 1 1
27WRONG!
28When 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???
29More 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 /
30Parentheses
- ANSI standard guarantees 32 levels of parentheses
nesting - enough to satisfy Mr. Scheme Kurt Eiselt
31More shootin
- define SQUARE(X) (X X)
- int z SQUARE(2)
- int z SQUARE(x y)
- Fix
- define SQUARE(X) ((X) (X))
OK?
32NOT!
- 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)
33NOT!
- 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 /
34Another 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?
35What happens?
- / Macro /
- SQUARE(x)
- .
- .
- .
- SQUARE(x)
- .
- .
- .
- SQUARE(x)
-
- / Function /
- square(x)
- .
- .
- .
- square(x)
- .
- .
- .
- square(x)
36What happens?
- / Macro /
- ((x) (x))
- .
- .
- .
- ((x) (x))
- .
- .
- .
- ((x) (x))
-
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
43What 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
44Macros 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?
45Macros 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!!!
46Inline
- 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
47Questions?
48Pop Quiz
- Write a macro to automatically check for return
values from printf
49Recall
- printf("some stuff d f", i, x)
- Problem We're ignoring the return value which
could indicate a problem
50We 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!
51First 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?
52Not 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 ) )
-
53Questions?
54(No Transcript)