See through C Module 5 Macros and preprocessors Tushar B Kute http://tusharkute.com
The C preprocessor and its role 2 cpp (C preprocessor) cc1 (C compiler) source program compiled code C compiler (e.g., gcc) expanded code • 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 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 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 1 or • #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 %sn", __FILE__); Predefined Macros
Adapted originally from: CSc 352 An Introduction to the C Preprocessor Saumya Debray Dept. of Computer Science The University of Arizona, Tucson debray@cs.arizona.edu Thank you This presentation is created using LibreOffice Impress 3.6.2.2

Module 05 Preprocessor and Macros in C

  • 1.
    See through C Module5 Macros and preprocessors Tushar B Kute http://tusharkute.com
  • 2.
    The C preprocessorand its role 2 cpp (C preprocessor) cc1 (C compiler) source program compiled code C compiler (e.g., gcc) expanded code • 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, …)
  • 3.
    #include • Specifies thatthe 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
  • 4.
    #include : Example 4 apredefined include file that: • comes with the system • gives type declarations, prototypes for library routines (printf) where does it come from? – man 3 printf :
  • 5.
    #include: cont’d • Wecan 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
  • 6.
    Macros • A macrois 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
  • 7.
    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; 
  • 8.
  • 9.
    Example 2 9 we can“macroize” symbols selectively
  • 10.
    Parameterized macros • Macroscan 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
  • 11.
  • 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 12
  • 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: 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++
  • 14.
    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
  • 15.
    Header Files • Havea file extension “.h” • Contain shared definitions – typedefs – macros – function prototypes • referenced via “#include” directives 15
  • 16.
  • 17.
    typedefs • Allow usto 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
  • 18.
    Example 18 defines “wcnode” asan alias for “struct wc” we can use “wcnode” in place of“struct wc” but not here, since “wcnode” has not yet been defined
  • 19.
    What if afile is #included multiple times? 19 foo.h bar1.h bar2.h bar.c
  • 20.
    Conditional Compilation: #ifdef #ifdefidentifier 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 20 line1 … linen will be included if identifier has been defined as a macro; otherwise nothing will happen.
  • 21.
    Conditional Compilation: #ifndef #ifndefidentifier line1 … linen #endif 21 line1 … linen will be included if identifier is NOT defined as a macro; otherwise nothing will happen.
  • 22.
    Solution to multipleinclusion 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
  • 23.
    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
  • 24.
    Generalizing #ifdef #if constant-expression line1 … linen #endif ⇒line1 … linen included if constant-expression evaluates to a non-zero value 24 Common uses: • #if 1 or • #if 0
  • 25.
    __LINE__ current linenumber 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 %sn", __FILE__); Predefined Macros
  • 26.
    Adapted originally from: CSc352 An Introduction to the C Preprocessor Saumya Debray Dept. of Computer Science The University of Arizona, Tucson debray@cs.arizona.edu Thank you This presentation is created using LibreOffice Impress 3.6.2.2