8/7/2019 Macros 97 http://slidepdf.com/reader/full/macros-97 1/33 Preprocessor Vijaya Saradhi
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 1/33
Preprocessor
Vijaya Saradhi
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 2/33
Introduction
� Header files
� Macros
� Conditionals
� Examples
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 3/33
Header files
� A file containing declarations and macros
� Usage of header files: #include
� # stands for preprocessing directive� Two types:
± System header files stdio, stdlib, stdargs,
± Our own hears containing declarations, macros� System headers resides at designated places
± /usr/include; /usr/local/include; etc
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 4/33
Headers
� Inclusion:
± #include<stdio.h>
± stdio.h is a file located at: /usr/include directory ± #include min.h
± min.h is a file located in the current directory
� Can specify path explicitly
± #include /home/guest/min.h
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 5/33
Example
File Name: min.h:
Located at: /home/guest
int min(int, ...);int max(int, ...);
void myprint(char *format, ...);
File Name: min.c:
#include<stdio.h>
#include ³/home/guest/min.h´
int main(int argc, char *argv[])
{
int k = 10, j = 20;
k = min(4, 5, 4, 3, 2);
k = min(6, 7, 6, 5, 4, 3, 2);
k = max(4, 5, 4, 3, 2);k = max(6, 7, 6, 5, 4, 3, 2);
myprint(³%d%d\n´, k, j);
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 6/33
Search Path
� Header files can be located at any place
� They can be included in any C program file
� How the compiler knows where to pick thesefiles?
� standard library files and other systems files
are searched in a specified locations� We can request compiler to search at
specified locations as well
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 7/33
Example
� You have two directories:
± assignment1
� src
� include
± At the time of compiling:
� gcc min.c I/home/guest/assignment1/include
± Our header files shall be searched in the given path
± Causes to place the contents in the required files
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 8/33
Macros
� Identifier following #define
� A fragment of code which has been given aname
� Two kinds: ± Object like macro resembles data objects
± Function like macro resembles functions
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 9/33
Object like macro
� A simple identifier
� This will be replaced by the code fragment
� Creating object like macro: ± #define MAX_ARRAY_SIZE 100
± #define TABLE_SIZE 200
± #define max_characters 1024
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 10/33
Example
#include<stdio.h>
#define MAX_ARRAY_SIZE 100
int main(int argc, char *argv[])
{int a[MAX_ARRAY_SIZE];
int a[100];
float f[MAX_ARRAY_SIZE];
float f[100];
..
..
}
Pre-processor recognizes and expands the macro
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 11/33
Close look
� Macro ends at the #define line
� For a macro running multiple lines:#define NUMBERS 10,\
11,\
12,\
13,\
14
int x[] = {NUMBERS};
Causes: int x[] = {10, 11, 12, 13, 14};
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 12/33
Function like macro
� Macros whose use looks like a macro
� Creating function like macro:
� Macros with arguments:
� #define identifier( id1, id2, , idk) string
#include<stdio.h>
#define print() printf(³Hello CS101\n´)
int main(int argc, char *argv[])
{print();
printf(³Hello CS101\n´);print();
printf(³Hello CS101\n´);
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 13/33
Example
#include<stdio.h>
#define sq(x) x * x
int main(int argc, char *argv[])
{int k = 5;
printf(³%3d\n´, sq(k));
printf(³%3d\n´, k * k);
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 14/33
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 15/33
Multi-line macro
#include<stdio.h>
#define FILL(array, size) \
for( i = 0; i < size; i++ ) \
array[i] = rand()
#define print(array, size, fmt) \for( i = 0; i < size; i++ ) \
printf(fmt, array[i])
int main(int argc, char *argv[])
{
int i = 0, a[10];
FILL(a, 10);
for( i = 0; i < 10; i++ )
a[i] = rand();
print(a, 10, ³%3d´);
for( i = 0; i < 10; i++ )
printf(fmt, a[i]);
return 0;}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 16/33
Variadic Macros
� A macro can be declared to accept variable
number of arguments#include<stdio.h>
#define eprintf(...) fprintf(stdout, __VA_ARGS__ )
int main(int argc, char *argv[])
{
int k = 10;
double d = 70.7;eprintf(³k: %-4d d: %4.2\n´, k, d);
fprintf(stdout, ³k: %-4d d: %4.2\n´, k, d);
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 17/33
Pitfalls
� Operator precedence:#include<stdio.h>
#define sq(x) x * x
#define sq(x) ((x) * (x))
int main(int argc, char *argv[])
{
int k = sq( 4 + 5 );
int k = 4 + 5 * 4 + 5;
int k = ((4 + 5) * (4 + 5));
printf(³k: %d\n´, k);
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 18/33
Pitfalls
#include<stdio.h>
#define FILL(array, size) \
for( i = 0; i < size; i++ ) \
array[i] = rand();
#define print(array, size, fmt) \
for( i = 0; i < size; i++ ) \
printf(fmt, array[i]);
int main(int argc, char *argv[])
{int i = 0, a[10], not_filled=1;
if( not_filled == 1 )
FILL(a, 10);
else
printf(³filled\n´);
if( not_filled = 1 )
for( i = 0; i < 10; i++ )
a[i] = rand();;
else
printf(³filled\n´);
Introduction of empty statement
� Swallowing of semicolon
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 19/33
Pitfalls
� Duplication#include<stdio.h>
#define MAX(x, y) ( (a) > (b) ? (a) : (b) )
int main(int argc, char*argv[])
{
int x = 5, y = 8, z = 0;
z = MAX(x++, y++);
z = ( (x++) > (y++ ) ? (x++) : (y++) );
printf(³x: %d, y: %d, z: %d\n´, x, y, z);
return 0;
}
output: x: 6, y: 10, z: 9
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 20/33
Pitfalls
� Self referential macros: A macro whose name
appears in its definition#include<stdio.h>
int main(int argc, char *argv[])
{
int x = 120;
#define x (10 + x)
printf(³%d\n´, x);printf(³%d\n´, (10 + x));
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 21/33
Self-referral macros
� Indirect self-referral: Does not go into infinite
loop of expanding macros x, y#define x (4 + y)
#define y (2 + x)
x expands to: (4 + y) -> (4 + (2 + x))
y expands to: (2 + x) -> (2 + (4 + y))
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 22/33
Pitfalls
� Mis-nesting:#include<stdio.h>
#define once(x) x(1)
#define twice(x) (2 * (x))
int main(int argc, char *argv[])
{
printf(³%d\n´, once(twice));
printf(³%d\n´, twice(1));
printf(³%d\n´, (2 * (1)));
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 23/33
At compilation
� One can define object like macro at
compilation time#include<stdio.h>
int main(int argc, char *argv[]){
int a[ MAX_ARRAY_SIZE];
float f[ MAX_ARRAY_SIZE];
for( k = 0; k < MAX_ARRAY_SIZE; k++ )
{a[i] = 10; f[i] = 70.7;
}
return 0;
}
gcc ±D MAX_ARRAY_SIZE=10 macro.c
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 24/33
Recollect
� Macros
± getchar() : #define getchar() getc(stdin)
± putchar(c) : #define putchar(c) putc( (c) , stdout)
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 25/33
Conditional Compilation
� Preprocessor has directives for conditionalcompilation
� Use of constructs: ± #ifdef, #ifndef
± #if, #else, #elif
± #defined()#include<stdio.h>
int main(int argc, char *argv[])
{
#ifdef DEBUGprintf(³Debug: Hello CS101 student\n´);
#endif
printf(³Hello CS101\n´);
return 0;
}
Compile:
gcc macro2.c ±DDEBUG=1Output:
Debug: Hello CS101 studentHello CS101
Compile:gcc macro2.cOutput:
Hello CS101
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 26/33
Conditional Compilation Contd.
� If a particular macro is *NOT* defined then
take some actions
#include<stdio.h>int main(int argc, char *argv[])
{
#ifndef DEBUGprintf(³No Debug: Hello CS101\n´);
#endifprintf(³Hello CS101 student\n´);
return 0;
}
Compile:
gcc macro2.c ±DDEBUG=1Output:
Hello CS101 student
Compile:gcc macro2.cOutput: No Debug: Hello CS101
Hello CS101 student
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 27/33
#If
� #ifdef/#if ndef checked for existence of macro
� #if allows evaluate arithmetic expression#include<stdio.h>
int main(int argc, char *argv[])
{
#if (10 < 20)
printf(³True\n´);
#else
printf(³False\n´);
#endif
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 28/33
Arithmetic expression
� Involves
± Integer constants
± Character constants
± Arithmetic operators: +, -, /, *
± Logical: ||, &&
± Bitwise: &, |, !
± Shit operators: <<, >>
± Macros
± defined operator
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 29/33
defined
� Special operator
± Checks whether a name is a defined macro or not
± Returns 1 if true
± 0 otherwise#include<stdio.h>
int main(int argc, char *argv[])
{
#if defined( LI NUX ) && !defined(W I NDOWS)
printf(³I am in Linux\n´);#else
printf(³I am in Windows\n´);
#endif
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 30/33
Undefine a macro
� We can un-define a (object and/or function
like) macro
� When you include files having macros;
� First un-define them to overwrite the new
definitions#include<stdio.h>
#define MAX_ARRAY_SIZE 100
int main(int argc, char *argv[])
{
int a[MAX_ARRAY_SIZE];
#undef MAX_ARRAY_SIZE
..
return 0;
}
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 31/33
#error
� During compilation, #error directive helps
throw errors.
#if 10 < 20
#error ³Incompatible sizes´
#endif
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 32/33
Pragma
� Causes behavior dependent on particularcompiler
� Want an identifier to not recognize
± Example: printf, scanf
± Poison them using poison pragma#include<stdio.h>
# pragma GCC poison printf scanf
int main(int argc, char *argv[])
{
int k = 10; double d = 70.7;
printf(³k: %d, d: %f\n´, k, d);
return 0;
gcc macro6.c ±g
macro6.c:9:3: error: attempt to
use poisoned printf
8/7/2019 Macros 97
http://slidepdf.com/reader/full/macros-97 33/33
Line numbers
� Use of #line causes renumbering of lines of
the source fileFile Name: macro7.c
1: #include<stdio.h>2:
3: int main(int argc, char *argv[])
4: {
5: #line 100 ³cs101.c´
100: printf(³Hello CS101 %s::%d\n´, __ FILE__, __ LI NE__ );101: return 0;
102:}
Output: Hello CS101: cs101.c::100