See through C
Module 5
Macros and preprocessors
Tushar B Kutehttp://tusharkute.com
The C preprocessor and its role
2
cpp(C preprocessor)
cc1(C compiler)
sourceprogram
compiledcode
C compiler (e.g., gcc)
expandedcode
• 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, …)
#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
3
#include : Example
4
a predefined include file that:• comes with the system• gives type declarations,
prototypes for library routines (printf)
where does it come from?– man 3 printf :
#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”
5
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 1024
#define WORDLEN 64
6
Using simple macros
• We just use the macro name in place of the value, e.g.:
#define BUFLEN 1024
#define Pi 3.1416
…
char buffer[BUFLEN];
…
area = Pi * r * r;
7
NOT: #define BUFLEN = 1024 #define Pi 3.1416;
Example 1
8
Example 2
9
we can “macroize” symbols selectively
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
10
no space here!(else preprocessor will assume we’re defining
a simple macro
Example
11
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
12
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:
13
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++);printf(“u = %d, v = %d”, u, v);
prints: u = 12, v = 21
Dbl(u++) expands to:u++ + u++
Properties of macros
• Macros may be nested
– in definitions, e.g.:
#define Pi 3.1416
#define Twice_Pi 2*Pi– in uses, e.g.:
#define double(x) x+x
#define Pi 3.1416
…
if ( x > double(Pi) ) …• Nested macros are expanded recursively
14
Header Files
• Have a file extension “.h”
• Contain shared definitions
– typedefs– macros– function prototypes
• referenced via “#include” directives
15
Header files: example
16
typedefs
• Allow us to define aliases for types
• Syntax:
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;
17
Example
18
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
What if a file is #included multiple times?
19
foo.h
bar1.h bar2.h
bar.c
Conditional Compilation: #ifdef
#ifdef identifierline1
…
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
20
line1 … linen will be included if identifier has been defined as a macro; otherwise nothing will
happen.
Conditional Compilation: #ifndef
#ifndef identifier
line1
…
linen
#endif
21
line1 … linen will be included if identifier is NOT defined as a macro; otherwise
nothing will happen.
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 ‘_’
22
indicates whether or not this file has been
included already
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:
#ifdef DEBUG
#define DMSG(msg) printf(msg) // debugging output
#else
#define DMSG(msg) {} // empty statement
#endif
23
straightforward, but needs discipline to use consistently
Generalizing #ifdef
#if constant-expression
line1
…
linen
#endif
⇒ line1 … linen included if constant-expression evaluates to a non-zero value
24
Common uses:• #if 1or• #if 0
__LINE__ current line number of the source file__FILE__ name of the current source file__TIME__ time of translation__STDC__ 1 if the compiler conforms to ANSI C
printf("working on %s\n", __FILE__);
Predefined Macros
Adapted originally from:
CSc 352An Introduction to the C Preprocessor
Saumya Debray
Dept. of Computer Science
The University of Arizona, Tucson
Thank you
This presentation is created using LibreOffice Impress 3.6.2.2
Top Related