Preprossecor Directive
Preprossecor Directive
1. The first step in compiling any C program is the preprocessor, a sort of automated editor
that modifies ( a copy of ) the source code before passing it on to the compiler to translate
into machine language code.
2. One of the tasks of the preprocessor is to strip off all comments, which the compiler
ignores.
3. The preprocessor also responds to directives in the code, which give the preprocessor
explicit instructions on how to edit the source code before passing it on to the compiler.
I. MACRO SUBSTITUTION
The #define directive is used to "define" preprocessor "variables", which can then be
used in one of three ways, as shown in the following three sections.
It is also possible to define preprocessor variables when invoking the compiler, either as
command-line arguments or through the IDE.
Sometimes the preprocessor only needs to know whether a particular preprocessor
variable is defined or undefined.
In this case, use #define and #undef to turn such variables "on" or "off"
Then you can turn all such blocks on or off at once using
#define DEBUG
or
#undef DEBUG
The most common use for #define is for automatic substitution of a text string.
Macros operate much like functions, but because they are expanded in place they are generally
faster, since they do not invoke the overhead of transferring control over to a function and then
transferring control back again.
However there are some potential dangers when using macros instead of functions, as described
below.
Example:
Explanation:
Note: It is very important to include parentheses around all variables used in a preprocessor
macro, as well as around the entire definition.
...
abSquared = SQUARE( a + b );
...
a_over_b_squared = a / SQUARE( b );
...
Preprocessor macros can span multiple lines only if the end of line is explicitly escaped:
(a) : \
(b) )
Note that macros do not check the types of their arguments, which can have both good and bad
consequences.
There are a number of macros automatically pre-defined by the compiler, inlcuding the following
list. Note that each one begins and ends with TWO underscore characters:
The #pragma Preprocessor Directive- It is used to give the preprocessor ( and compiler )
specific details on exactly how to compile the program. For example, specific compiler warnings
can be ignored, or warning levels changed up or down for different sections of code.
Examples:
#pragma page( ) // Forces a form feed in the listing
#pragma line 100 // Sets the current line number to 100 for listing and reporting purposes.
#include <file>
or
#include ``file''
<file> tells the compiler to look where system include files are held.
Usually UNIX systems store files in user include directory.
``file'' looks for a file in the current directory (where program was run from)
Included files usually contain C prototypes and declarations from header files
and not (algorithmic) C code (SEE next Chapter for reasons)
#if -- Conditional inclusion It evaluates a constant integer expression. You always need
a #endif to delimit end of statement.
We can have else etc. as well by using #else and #elif -- else if.
#ifdef
-- if defined
#ifndef
-- if not defined
These are useful for checking if macros are set -- perhaps from different program modules and
header files.
#if 1
#endif
#if 0
#endif
The conditional expression could contain any C operator except for the assignment
operators, the increment and decrement operators, the address-of operator, and the sizeof
operator.
One unique operator used in preprocessing and nowhere else is the defined operator. It
returns 1 if the macro name, optionally enclosed in parentheses, is currently defined; 0 if
not.
The #endif command ends a block started by #if, #ifdef, or #ifndef.
The #elif command is similar to #if, except that it is used to extract one from a series of
blocks of code. E.g.:
#else
#ifdef NAME
is equivalent to
The #ifndef command is similar to #ifdef, except that the test is reversed:
#ifndef NAME
is equivalent to
Example-1:
For example, to set integer size for a portable C program between TurboC (on MSDOS) and
Unix (or other) Operating systems. Recall that TurboC uses 16 bits/integer and UNIX 32
bits/integer.
Assume that if TurboC is running a macro TURBOC will be defined. So we just need to check
for this:
#ifdef TURBOC
#define INT_SIZE 16
#else
#define INT_SIZE 32
#endif
Example-2:
As another example if running program on MSDOS machine we want to include file msdos.h
otherwise a default.h file. A macro SYSTEM is set (by OS) to type of system so check for this:
#include <msdos.h>
#else
#include ``default.h''
#endif
The -E command line is worth mentioning just for academic reasons. It is not that practical a
command. The -E command will force the compiler to stop after the preprocessing stage and
output the current state of your program. Apart from being debugging aid for preprocessor
commands and also as a useful initial learning tool (try this option out with some of the examples
above) it is not that commonly used.
#ifdef OS_MSDOS
#include <msdos.h>
#elifdef OS_UNIX
#include ``default.h''
#else
#endif
#error
The #error directive halts compilation. When one is encountered the standard specifies that the
compiler should emit a diagnostic containing the remaining tokens in the directive. This is
mostly used for debugging purposes.
#error
#error token-sequence
# line
number "string" -- informs the preprocessor that the number is the next number of line of
input. "string" is optional and names the next line of input. This is most often used with
programs that translate other languages to C. For example, error messages produced by the C
compiler can reference the file name and line numbers of the original source files instead of the
intermediate C (translated) source files.
They are represented in 2 ways
#line constant
#line constant “filename”