Presentation is loading. Please wait.

Presentation is loading. Please wait.

CSc 352 An Introduction to the C Preprocessor

Similar presentations


Presentation on theme: "CSc 352 An Introduction to the C Preprocessor"— Presentation transcript:

1 CSc 352 An Introduction to the C Preprocessor
Saumya Debray Dept. of Computer Science The University of Arizona, Tucson

2 The C preprocessor and its role
text: Ch. 14 C compiler (e.g., gcc) cpp (C preprocessor) cc1 (C compiler) compiled code source program expand some kinds of characters discard whitespace and comments each comment is replaced with a single space process directives: file inclusion (#include) macro expansion (#define) conditional compilation (#if, #ifdef, …) expanded code

3 #include Specifies that the preprocessor should read in the contents of the specified file usually used to read in type definitions, prototypes, etc. proceeds recursively #includes in the included file are read in as well Two forms: #include <filename> searches for filename from a predefined list of directories the list can be extended via “gcc –I dir” #include “filename” looks for filename specified as a relative or absolute path

4 #include : Example where does it come from? man 3 printf :
a predefined include file that: comes with the system gives type declarations, prototypes for library routines (printf)

5 #include: cont’d We can also define our own header files:
a header file has file-extension ‘.h’ these header files typically contain “public” information type declarations macros and other definitions function prototypes often, the public information associated with a code file foo.c will be placed in a header file foo.h these header files are included by files that need that public information #include “myheaderfile.h”

6 Macros A macro is a symbol that is recognized by the preprocessor and replaced by the macro body Structure of simple macros: #define identifier replacement_list Examples: #define BUFFERSZ #define WORDLEN 64

7 Using simple macros We just use the macro name in place of the value, e.g.: #define BUFLEN 1024 #define Pi char buffer[BUFLEN]; area = Pi * r * r; NOT: #define BUFLEN = 1024 #define Pi ;

8 Example 1

9 we can “macroize” symbols selectively
Example 2 we can “macroize” symbols selectively

10 (else preprocessor will assume we’re defining a simple macro
Parameterized macros Macros can have parameters these resemble functions in some ways: macro definition ~ formal parameters macro use ~ actual arguments Form: #define macroName(arg1, …, argn) replacement_list Example: #define deref(ptr) *ptr #define MAX(x,y) x > y ? x : y no space here! (else preprocessor will assume we’re defining a simple macro

11 Example

12 Macros vs. functions Macros may be (slightly) faster
don’t incur the overhead of function call/return however, the resulting code size is usually larger this can lead to loss of speed Macros are “generic” parameters don’t have any associated type arguments are not type-checked Macros may evaluate their arguments more than once a function argument is only evaluated once per call

13 Macros vs. Functions: Argument Evaluation
Macros and functions may behave differently if an argument is referenced multiple times: a function argument is evaluated once, before the call a macro argument is evaluated each time it is encountered in the macro body. Example: Dbl(u++) expands to: u u++ int dbl(x) { return x + x;} u = 10; v = dbl(u++); printf(“u = %d, v = %d”, u, v); prints: u = 11, v = 20 #define Dbl(x) x + x u = 10; v = Dbl(u++); prints: u = 12, v = 21

14 Properties of macros Macros may be nested
in definitions, e.g.: #define Pi #define Twice_Pi 2*Pi in uses, e.g.: #define double(x) x+x #define Pi if ( x > double(Pi) ) … Nested macros are expanded recursively

15 Pitfalls of nested macros
Oops!

16 What happened? textual replacement!

17 Avoiding the problem

18 What happened

19 Header Files Have a file extension “.h” Contain shared definitions
typedefs macros function prototypes referenced via “#include” directives

20 Header files: example

21 typedefs Allow us to define aliases for types Syntax: Example:
typedef old_type_name new_type_name; new_type_name becomes an alias for old_type_name Example: typedef int BasePay; typedef struct node { int value; struct node *next; } node;

22 Example defines “wcnode” as an alias for “struct wc”
we can use “wcnode” in place of“struct wc” but not here, since “wcnode” has not yet been defined

23 What if a file is #included multiple times?
foo.h bar1.h bar2.h bar.c

24 Example of multiple inclusions

25 Problems with multiple inclusions

26 Solution to multiple inclusion problem
Use conditional compilation to ensure that a header file is “really included” at most once header file’s responsibility to protect itself from multiple-inclusion problems uses a conditional-compilation directive #ifndef in effect sets a flag when a file is included so we don’t include it again relies on convention we need to understand it so we don’t break it

27 Conditional Compilation: #ifdef
#ifdef identifier line1 linen #endif macros can be defined by the compiler: gcc –D macroName gcc –D macroName=definition macros can be defined without giving them a specific value, e.g.: #define macroName line1 … linen will be included if identifier has been defined as a macro; otherwise nothing will happen.

28 Conditional Compilation: #ifndef
#ifndef identifier line1 … linen #endif line1 … linen will be included if identifier is NOT defined as a macro; otherwise nothing will happen.

29 Solution to multiple inclusion problem
The header file is written as follows: #ifndef file_specific_flag #define file_specific_flag …contents of file… #endif file_specific_flag usually constructed from the name of the header file: E.g.: file = foo.h  flag = _FOO_H_ try to avoid macro names starting with ‘_’ indicates whether or not this file has been included already

30 straightforward, but needs discipline to use consistently
Another use of #ifdefs They can be useful for controlling debugging output Example 1: guard debugging code with #ifdefs: #ifdef DEBUG …debug message… #endif Example 2: use the debug macro to control what debugging code appears in the program: #define DMSG(msg) printf(msg) // debugging output #else #define DMSG(msg) {} // empty statement straightforward, but needs discipline to use consistently

31 Example 1(a)

32 to address the “too many arguments to macro” problem
Example 1(b) to address the “too many arguments to macro” problem “too many arguments” issue resolved, but the macro expansion isn’t working quite the way we want

33 Example 1(c)

34 Generalizing #ifdef #if constant-expression line1 … linen #endif  line1 … linen included if constant-expression evaluates to a non-zero value Common uses: #if 1 or #if 0


Download ppt "CSc 352 An Introduction to the C Preprocessor"

Similar presentations


Ads by Google