C Preprocessor Directives and Macros

    1 Votes

C pre-processor directives help us to modify the program text before it is compiled. Basically, C pre-processors directives have the capability of simple text substitution tool, so that you can modify parts of program before it's actually compiled. We've already used few of the C pre-processors in the examples discussed in different chapters of this C programming tutorial. One of them is #include pre-processor directive which includes a header file into the program. Apart from including header files, there are other C pre-processor directives also which allow us to define a constant, write macros etc. C pre-processor comes in handy if you want some part of your code to be compiled depending on some condition. It is also known as conditional compilation.

Macro Definition in C

The macro can be used to define code that would be in-lined to the source code before compilation. The macro can be of two types, object likes (macro without arguments) and function like (macro with arguments or parameterized macros). Object like macro does not take any argument where function type macro resembles a function as it takes arguments like functions.

The object type macro can be used to define any constant value. For this, you have to use define keyword with hash (#) sign preceding it. If you want to declare a constant have the value of Pi, which is (3.14), you can do it as given below

#define PI 3.14

Here PI is the constant, having value 3.14. You can write macros in upper case or lower case, but using upper case letters is considered as good programming practice. This allows you to distinguish constants from variables. You would also notice that the define statement does not have any semicolon following it.

Once you've defined a macro, you can use it in the program as given below.

area = PI * radius * radius;

If you want to change the value of its content from the some part of the program, you have to use another pre-processor directive #undef first to invalidate the initial #define. Let's consider following example.

Example of #undef and #define Macros in C

#define A 2					
void main()
    printf("First value: %d\n", A);
    #undef A
    #define A 3
    printf("Second value: %d", A);

The above program will generate the output as "First value: 2" and in the second line "Second value: 3". At first, we defined the value of 'A' as 2 and, after first 'printf', the '#undef' code will undefine the value of 'A' and the following 'define' statement will define it again with value 3. Please note that all these happens before actual compilation of program

#include pre-processor Directive

We have already used '#include' directive a number of times in different examples discusses so far. This pre-processor is used for file inclusion. Using '#include' pre-processor causes the definition of header file to be included in the source file. That way when we are using functions from different header files, like 'printf', program knows what these functions do. It is also useful for inclusion of the user defined header files as well. There are two ways to write '#include' directive.

#include <header_file.h>
#include "header_file.h"

Both of the above statements include the header file specified as part of it, the only difference is in the search path of the header file. If we use angular brackets (< >), then the header file is searched in the system defined path. In the case of double quotation (" "), the header file will be searched first in the current path, i.e. the path where the source file is. Mainly we use angular brackets when including a system provided header file and double quotes are used when including header files written by the programmer.

Macro Function/Parameterized Macros

The macros we have used until now are without any arguments. Macros can have arguments too, like the functions. Such macro definitions are called parameterized macros. A simple example of parameterized macro definition is given below

Parameterized Macro Example in C

#define SQUARE(x)  (x * x)					
void main()
    int i = 3;
    int sq = SQUARE(i);
	printf("Square value: %d\n", sq);

This program will generate output as "Square value: 9". But there is something different in parameterized macro in comparison with functions in C. Macro definitions are in-lined in the program, which means the definition of the macro 'SQUARE'will be replaced in the program before compilation. So, the statement

int sq = SQUARE(i);

will be replaced by

int sq = (i * i);

The advantage of using the macro is that it does not depend on the type of the arguments and also the macro function is in-lined. It is also a disadvantage of macro. Consider the above macro function 'SQUARE', and we use it in the program as SQUARE( i + 1). We know that value of 'i' is 3 and so the expected output should be 16. But the reality is quite different. As the macro is inlined, SQUARE(i + 1) will be replaced by (i + 1 * i + 1). Now the precedence of operator '+' is lower than '*'. So the statement will be treated as (i + (1 * i ) + 1) and will generate output 7. One way to avoid this, is by using parenthesis in macro, like

#define SQUARE(x) ((x) * (x))
or where we used the macro, like
int sq = SQUARE((i + 1));

Multi-Lined Macros

The macro functions can be multi line statements also. To write multiline macro, each line must be followed by a backslash ("\") except the last line. A multiline macro looks like the following

Multiline Macro Example in C

#define ABC(n)\
for(i = 0; i < n; i++)\
    printf("%d\n", i);\

Also Read - Top C Interview Questions and Answers for Freshers & Advanced C Interview Questions and Answers

#pragma Pre-processor Directive

Pragma is used to turn on or off some of compiler/system features. Pragma's operation is system and compiler dependent. So, all pragmas may not work with all the compilers. When pragmas are encountered, the default behaviour of the compiler is overwritten by the options provided by pragmas. One of such pragma is 'pragma startup' and 'pragma exit'. The pragma startup is used to specify function that will be called before main function and pragma exitis used to specify function that would be called just before the program exits. Consider the example program

Pragma Example in C


void function1();
void function2() ;

#pragma startup function1
#pragma exit function2

void main()
	printf("In main function");

void function1()
	printf("In function1\n");

void function2()
	printf("In function2");

In function1
In main function
In function2		

Also Read - Top Embedded C Interview Questions and Answers & C++ Interview Questions and Answers

Conditional Compilation pre-processors

There are other C pre-processors like #if, #elif, #else, #endif etc which are used for conditional compilation. If we want to skip over a part of code during compilation, we can use these pre-processors. This is mostly useful when we write code which depends on the operating system. Suppose, some code we have written is not applicable for Windows and only applicable for Linux machines, we can skip the code, when compiling from Windows machine using this pre-processors. The general form of #ifdefis

#ifdef macroname
Statement block;

The '#ifdef' stands for 'if defined'. It means that if the macro name is already defined somewhere, then the statement block will be included in the source for compilation, otherwise it will be skipped. The #ifdefis accompanied by an #endif statement, which marks the end of statement block. We can use #ifndef, which is applicable when we want to compile part of program if the corresponding macro name is not defined. Like nested if...else , #ifdef also can be combined with #elif and #else. We can use them as given in the below example.

Conditional Compilation Example in C

	statement block 1;
	statement block 2;
	statement block 3;

Predefined Macros

Apart from the above mentioned macros, ANCI has a set of predefined macros which can be used for functionalities that's used commonly in application programs. They are explained below.

__DATE__ Gives current date in MMM DD YYYY format
__TIME__ Gives current time in HH:MM:SS format
__FILE__ Gives the current file name
__LINE__ Gives the current line number of source code
__STDC__ Gives 1 when the compilation follows ANSI standard

Related Articles

C Overview and Basic Syntax
Data Types in C Language
C Qualifiers - Constant and Volatile type Qualifier
C Type Casting with examples - float to int / int to char / int to long
C Constants and Literals
C Operators - Arithmetic, Assignment, Relational and Logical
C Operators - Bitwise Operators and Conditional Operators
C Operator Precedence and Associativity Table with Examples
C Input and Output Statements
C Format Specifiers for printf and scanf
C Decision Making Control Structures - 'if', 'if - else', nested 'if', 'switch'
Loops in C - for, while and do...while Loops
C 'break', 'continue' and 'goto' Statements to Control Program Flow
C Functions Tutorial with Examples
C Arrays - Dynamic, 2d and Multidimensional with Examples
C Strings - Internal Working and Functions with example
C Pointers basics explained with examples
Structures in C Programming with Example
Unions in c programming with example
C Storage Class Specifiers - auto, register, static and extern

Popular Videos

How to Overcome Shyness in Communication

How to Overcome Shyness in Communication using 4 Simple Steps.

Got a tip or Question?
Let us know