Thursday, 1 May 2014

The C Preprocessor

The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation. It is called a macro processor because it allows you to definemacros, which are brief abbreviations for longer constructs.
The C preprocessor provides four separate facilities that you can use as you see fit:
  • Inclusion of header files. These are files of declarations that can be substituted into your program.
  • Macro expansion. You can define macros, which are abbreviations for arbitrary fragments of C code, and then the C preprocessor will replace the macros with their definitions throughout the program.
  • Conditional compilation. Using special preprocessing directives, you can include or exclude parts of the program according to various conditions.
  • Line control. If you use a program to combine or rearrange source files into an intermediate file which is then compiled, you can use line control to inform the compiler of where each source line originally came from.

Preprocessing Directives
Preprocessing directives are lines in your program that start with `#'. The `#' is followed by an identifier that is the directive name.

SL Number
Directive
Meaning
1
# include
include a source file
2
# define
define a macro
3
# undef
undefine a macro
4
# if
conditional compilation
5
# ifdef
conditional compilation
6
# ifndef
conditional compilation
7
# elif
conditional compilation
8
# else
conditional compilation
9
# endif
conditional compilation
10
# line
control error reporting
11
# error
force an error message
12
# pragma
used for implementation-dependent control
13
#
null directive; no effect

1.   #include
Both user and system header files are included using the preprocessing directive `#include'. This comes in two flavours:

#include < stdio.h >
#include "myheader.h"

both of which cause a new file to be read at the point where they occur.
The effect of using brackets <> or quotes " " around the filename is to change the places searched to find the specified file. <> directives tell the preprocessor to get stdio.h from System Libraries and add the text to the current source file. The next line tells preprocessor  to get myheader.h from the local directory and add the content to the current source file. If the form using " " can't find the file, it tries searching again from System Libraries. In general, brackets are used when you specify standard library header files, quotes are used for private header files—often specific to one program only.

 Once-Only Include Files
Very often, one header file includes another. It can easily result that a certain header file is included more than once. This may lead to errors, if the header file defines structure types or typedefs, and is certainly wasteful. Therefore, we often wish to prevent multiple inclusion of a header file.
The standard way to do this is to enclose the entire real contents of the file in a conditional, like this:


#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN

the entire file

#endif /* FILE_FOO_SEEN */

2.      
      # define
The #define creates a macro. A preprocessor define directive directs the preprocessor to replace all subsequent occurrences of a macro with specified replacement tokens.  A simple macro is a kind of abbreviation.
Before you can use a macro, you must define it explicitly with the `#define' directive. `#define' is followed by the name of the macro and then the code it should be an abbreviation for. For example,

#define BUFFER_SIZE 1020
defines a macro named `BUFFER_SIZE' as an abbreviation for the text `1020'. If somewhere after this `#define' directive there comes a C statement of the form

foo = (char *) xmalloc (BUFFER_SIZE);
then the C preprocessor will recognize and expand the macro `BUFFER_SIZE', resulting in

foo = (char *) xmalloc (1020);

3.   # undef
The name of any #defined identifier can be forcibly forgotten by saying

#define WIDTH 80
#define ADD( X, Y ) ((X) + (Y))
#undef WIDTH
#undef ADD

To remove a macro definition using #undef, give only the macro identifier; do not give a parameter list.
4.   
       #if, #elif, #else, and #endif Directives 
The #if directive, with the #elif#else, and #endif directives, controls compilation of portions of a source file. Each  #if directive in a source file must be matched by a closing #endif directive. Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. The #else directive, if present, must be the last directive before #endif.
#if defined(CREDIT)
    credit();
#elif defined(DEBIT)
    debit();
#else
    printerror();
#endif

Each #if directive in a source file must be matched by a closing #endif directive. Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. The #else directive, if present, must be the last directive before #endif.
The #if#elif#else, and #endif directives can nest in the text portions of other #if directives. Each nested #else,#elif, or #endif directive belongs to the closest preceding #if directive. All conditional-compilation directives, such as #if and #ifdef, must be matched with closing #endif directives prior to the end of file; otherwise, an error message is generated.

#if DLEVEL > 5
    #define SIGNAL  1
    #if STACKUSE == 1
        #define STACK   200
    #else
        #define STACK   100
    #endif
#else
    #define SIGNAL  0
    #if STACKUSE == 1
        #define STACK   100
    #else
        #define STACK   50
    #endif
#endif
#if DLEVEL == 0
    #define STACK 0
#elif DLEVEL == 1
    #define STACK 100
#elif DLEVEL > 5
    display( debugptr );
#else
    #define STACK 200
#endif



The #ifdef and #ifndef directives perform the same task as the #if directive when it is used ith definedidentifier ).
#ifdef identifier
#ifndef identifier

// equivalent to
#if defined identifier
#if !defined identifier

You can use the #ifdef and #ifndef directives anywhere #if can be used. The #ifdef identifier statement is equivalent to #if 1 when identifier has been defined, and it is equivalent to #if 0 when identifier has not been defined or has been undefined with the #undef directive. These directives check only for the presence or absence of identifiers defined with #define, not for identifiers declared in the C or C++ source code.
The #ifndef directive checks for the opposite of the condition checked by #ifdef. If the identifier has not been defined (or its definition has been removed with #undef), the condition is true (nonzero). Otherwise, the condition is false (0).

5.      
       #line
preprocessor line control directive supplies line numbers for compiler messages. It causes the compiler to view the line number of the next source line as the specified number. You can use #line control directives to make the compiler provide more meaningful error messages. 

/**
 ** This example illustrates #line directives.
 **/

#include <stdio.h>
#define LINE200 200

int main(void)
{
   func_1();
   func_2();
}

#line 100
func_1()
{
   printf("Func_1 - the current line number is %d\n",_ _LINE_ _);
}

#line LINE200
func_2()
{
   printf("Func_2 - the current line number is %d\n",_ _LINE_ _);
}

This program produces the following output:

Func_1 - the current line number is 102
Func_2 - the current line number is 202


6.       
      #error
The #error directive emits a user-specified error message at compile time and then terminates the compilation.
#if !defined(__cplusplus)
#error C++ compiler required.
#endif


7.   #pragma
There are many type of pragma directive and varies from one compiler to another compiler .If compiler does not recognize particular pragma the it simply ignore that pragma statement without showing any error or warning message and execute the whole program assuming this pragma statement is not present. For example  suppose there is any pragma directive is #pragma world .

#include<stdio.h>
#pragma world
int main(){
    printf("C is powerful language ");
    return 0;
}

Output : C is powerful language

Since #pragma world is unknown for Turbo c 3.0 compiler so it will ignore this directive without showing any error or warning message and execute the whole program assuming #pragma world statement is not present.


1.       #
The null preprocessor directive is a single number sign (#) alone on a line. It has no effect.



 Sources:


No comments:

Post a Comment