Professional Documents
Culture Documents
1
Uses of Conditonal
#define preprocessor directive
Compilation
• creates symbolic constants and • To make sure that a macro is defined at
least and at most once.
macros
#ifndef NULL or #if !defined(NULL)
#define PI 3.14159 #define NULL 0
#endif
identifier replacement-text
• to control the inclusion of debugging
statements
replaces all subsequent occurrences of the
#define DEBUG 1
symbolic constant PI with the numeric #if DEBUG == 1 or #ifdef DEBUG
constant 3.14159. code prevented from compiling
#endif
7 10
#define ABSDIFF(X,Y) ( (X) > (Y) ? (X) – (Y) : (Y) – (X) ) #pragma tokens
• causes an implementation defined action
ABSDIFF(I+1, J-5) • A pragma not recognized by an
implementation is ignored
Common programming error: Forgetting to enclose macro
arguments in parentheses in the replacement text. – Borland c++ recognizes several pragmas that
enable the programmer to take full advantage
8 of the Borland’s compiler 11
Predefined Symbolic
Conditional Compilation
Constants
• enables the programmer to control • __LINE__ line number of current source code line
the execution of preprocessor • __FILE__ presumed name of source file
directives and the compilation of • __DATE__ compilation date as Mmm dd yyyy
program code
• __TIME__ compilation time as hh:mm:ss
– Each of the conditional preprocessor
directives evaluates a constant integer • __STDC__ int constant 1, to indicate that
expression implementation is ANSI compliant
9 12
2
Assertions Recursive Macro Expansion
• assert macro is defined in assert.h • Invocation of one macro by another
– tests the value of an expression
– if value of expr is 0, becomes false
• prints an error message and calls abort • It is not difficult if the macro
function of stdlib.h to terminate program processor is being written in a
execution programming language that allows
assert (R != 0); recursive calls
x = y / R; – macro processor recursively processes
• if symbolic constant NDEBUF is defined the macros until all are resolved.
subsequent asserts will be ignored. Try:
– Use #define NDEBUG when assert is no longer DISPLAY(ABSDIFF(3,8))
needed
13 16
General-Purpose Macro
# and ##
Processors
• # stringizing operator • not dependent on any particular
– argument substitution is performed in the usual programming language, but can be
way, but the resulting string is enclosed in used with a variety of different
quotes
#define DISPLAY(EXPR) printf(#EXPR ”= %d\n”,EXPR) languages
vs. – Advantages:
#define DISPLAY(EXPR) printf(#EXPR ”= %d\n”,EXPR) • programmer does not need to learn about a
TRY: DISPLAY(I*J+1) different macro facility for each compiler or
assembler language
• costs involved in producing a different macro
• ## concats two tokens processor for each language is not needed
#define TOKENCONCAT( x, y) x##y
TRY: TOKENCONCAT(O, K) 14 17
15 18
3
• Implementation problems related to the • Integrated macro processor: instead
differences among langauges of passing information macro-
– There are several situations in which normal processor and translator, they are
macro parameter substitution should not occur
• e.g., different comment styles: /* */ or // combined as one unit.
– Grouping statements in languages highly differ – can potentially make use of any
• e.g., { }, begin end information about the source program
– Tokens and rules for forming tokens differ that is extracted by the language
• e.g., = and := translator
– syntax used for macro definitions and macro • special rules of the language are handled by
invocation statements should be similar to the translator
language to make it more readable and – ex: If macro involved substituting for the variable
writeable. name I in the FORTRAN statement DO 100 I = 1
19 22
• Advantages:
+ avoids making an extra pass over the
source program
+ more efficient – some of the data structures
can be combined
+ makes it easier to give diagnostic messages
related to the source statement containing
the error
21