Startertutorials Blog
Tutorials and articles related to programming, computer science, technology and others.
Subscribe to Startertutorials.com's YouTube channel for different tutorial and lecture videos.

Categories: C Programming. 2 Comments on Preprocessor Directives in C

This article provides a comprehensive overview of preprocessor directives in C programming language along with relevant examples.

 

C provides many features like structures, unions and pointers. Another unique feature of the C language is the preprocessor. The C preprocessor provides several tools that are not present in other high-level languages.

 

The programmer can use these tools to make his program easy to read, easy to modify, portable and more efficient. The preprocessor is a program that processes the source code before it passes through the compiler.

 

Preprocessor directives are placed in the source program before the main line. Before the source code passes through the compiler, it is examined by the preprocessor for any preprocessor directives. If there are any, appropriate actions are taken and then the source program is handed over to the compiler.

 

All the preprocessor directives follow special syntax rules that are different from the normal C syntax. Every preprocessor directive begins with the symbol # and is followed by the respective preprocessor directive. The preprocessor directives are divided into three categories. They are:

  1. Macro Substitution Directives
  2. File Inclusion Directives
  3. Compiler Control Directives

 

Macro Substitution Directives

 

Macro substitution is a process where an identifier in a program is replaced by a predefined string composed of one or more tokens. The preprocessor accomplishes this task under the direction of #define statement. This statement, usually known as a macro definition takes the following form:

 

macro-sub-directive

 

If this statement is included in the program at the beginning, then the preprocessor replaces every occurrence of the identifier in the source code by the string.

 

Note: Care should be taken that there is no space between the # and the word define. Also there should be atleast a single space between #define and the identifier and between the identifier and the string. Also, there will be no semi-colon at the end of the statement.

 

There are different forms of macro substitution. The most common are:

  1. Simple macro substitution
  2. Argumented macro substitution
  3. Nested macro substitution

 

Simple Macro Substitution

 

The simple macro substitutions are generally used for declaring constants in a C program. Some valid examples for simple macro substitution are:

 

define-examples

 

Whenever the preprocessor comes across the simple macros, the identifier will be replaced with the corresponding string. For example, in a C program, all the occurrences of PI will be replaced with 3.1412.

 

Argumented Macro Substitution

 

The preprocessor allows us to define more complex and more useful form of substitutions. The Argumented macro substitution takes the following form:

 

arg-macro

 

Care should be taken that there is no space between the identifier and the left parentheses. The identifiers arg1, arg2, …. , argn are the formal macro arguments that are analogous to the formal arguments in a function definition.

 

In the program, the occurrence of a macro with arguments is known as a macro call. When a macro is called, the preprocessor substitutes the string, replacing the formal parameters with actual parameters.

 

For example, if the Argumented macro is declared as shown below:

 

arg-macro-ex

 

and the macro is called as shown below:

 

arg-macro-call

 

Then the preprocessor will expand the above statement as:

 

arg-macro-call1

 

Nested Macro Substitution

 

We can use one macro inside the definition of another macro. Such macros are known as nested macros. Example for a nested macro is shown below:

 

nested-macro

 

 

File Inclusion Directives

 

The external files containing functions or macro definitions can be linked with our program so that there is no need to write the functions and macro definitions again. This can be achieved by using the #include directive. The syntax for this directive is as shown below:

 

include

 

We can use either of the above statements to link our program with other files. If the filename is included in double quotes, the file is searched in the local directory. If the filename is included in angular brackets, then the file is searched in the standard directories.

 

Compiler Control Directives

 

Following are the compiler control directives:

 

Directive Purpose
#ifdef Test for a macro definition
#endif Specifies the end of #if
#ifndef Tests whether a macro is not defined
#if Test a compile-time condition
#else Specifies alternative when #if fails

 

These compiler control directives are used in different situations. They are:

 

Situation 1

 

You have included a file containing some macro definitions. It is not known whether a certain macro has been defined in that header file. However, you want to be certain that the macro is defined.

 

This situation refers to the conditional definition of a macro. We want to ensure that the macro TEST is always defined, irrespective of whether it has been defined in the header file or not. This can be achieved as follows:

 

#include”DEFINE.H”
#ifndef TEST
#define TEST 1
#endif

 

DEFINE.H is the header that is supposed to contain the definition of TEST macro. The directive #ifndef TEST searches the definition of TEST in the header file and if it is not defined, then all the lines between the #ifndef and the corresponding #endif directive are executed in the program.

 

Situation 2

 

Suppose a customer has two different types of computers and you are required to write a program that will run on both the systems. You want to use the same program, although a certain lines of code must be different for each system.

 

The main concern here is to make the program portable. This can be achieved as shown below:

 

#ifdef IBM_PC
{
	----
	----
}
#else
{
	----
	----
}
#endif

 

If we want to run the program on a IBM PC, we include the directive #define IBM_PC, otherwise we won’t.

 

Situation 3

 

You are developing a program for selling in the open market. Some customers may insist on having certain additional features. However, you would like to have a single program that would satisfy both types of customers.

 

This situation is similar to the above situation and therefore the control directives take the following form:

 

#ifdef ABC
	Group-A lines
#else
	Group-B lines
#endif

 

Group-A lines are included if the customer ABC is defined. Otherwise, Group-B lines are included.

 

Situation 4

 

Suppose if you want to test a large program, you would like to include print calls in the program in certain places to display intermediate results and messages in order to trace the flow of execution and errors.

 

For this purpose we can use #if and #else directive as shown below:

 

#if constant expression
{
	Statement 1;
	Statement 2;
	-----
}
else
{
	Statement 1;
	Statement 2;
	-----
}
#endif

 

ANSI Preprocessor Directives

 

The ANSI committee has added some more preprocessor directives to the existing list. They are:

 

Directive Purpose
#elif Provides alternative test facility
#pragma Specifies compiler instructions
#error Stops compilation when an error occurs

 

#elif   Directive

 

The #elif directive enables us to establish an “if…else…if” sequence for testing multiple conditions. The syntax is as shown below:

 

#if expr1
	Stmts;
#elif  expr2
	Stmts;
#elif  expr3
	Stmts;
#endif

 

#pragma  Directive

 

The #pragma directive is an implementation oriented directive that allows the user to specify various instructions to be given to the compiler. Syntax is as follows:

 

#pragma name

 

Where name is the name of the pragma we want. For example, under Microsoft C, #pragma loop_opt(on)  causes loop optimization to be performed.

 

#error  Directive

 

The #error directive is used to produce diagnostic messages during debugging. The general format is:

 

#error  error-message

 

When the #error directive is encountered by the compiler, it displays the error message and terminates the program.

 

Example:

#if !defined(FILE_G)
#error NO GRAPHICS FILE
#endif

 

Preprocessor Operations

 

Stringizing Operator #

 

ANSI C provides an operator # called stringizing operator to be used in the definition of macro functions. This operator converts a formal argument into a string. For example, if the macro is defined as follows:

 

#define	    sum(xy)     printf(#xy  “ = %f \n”, xy)

 

and somewhere in the program the statement is written as: sum(a+b); then the preprocessor converts this line as shown below:

 

printf(“a+b”  “ = %f \n”, a+b);

 

Token Pasting Operator ##

 

The token pasting operator ## defined by ANSI enables us to combine two tokens within a macro definition to form a single token.

How useful was this post?

Click on a star to rate it!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Suryateja Pericherla

Suryateja Pericherla, at present is a Research Scholar (full-time Ph.D.) in the Dept. of Computer Science & Systems Engineering at Andhra University, Visakhapatnam. Previously worked as an Associate Professor in the Dept. of CSE at Vishnu Institute of Technology, India.

He has 11+ years of teaching experience and is an individual researcher whose research interests are Cloud Computing, Internet of Things, Computer Security, Network Security and Blockchain.

He is a member of professional societies like IEEE, ACM, CSI and ISCA. He published several research papers which are indexed by SCIE, WoS, Scopus, Springer and others.

2 Comments

You can follow any responses to this entry through the RSS 2.0 feed.

I like the article

Thanks for the terrific guide

Leave a Reply

Your email address will not be published. Required fields are marked *