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
#include<stdio.h> #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> or, #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
#include<stdio.h> #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 exit
is used to specify function that would be called just before the program exits. Consider the example program
Pragma Example in C
#include<stdio.h> 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"); } Output: 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 #ifdef
is
#ifdef macroname Statement block; #endif
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 #ifdef
is 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
#ifdef SYSTEM==LINUX statement block 1; #elif SYSTEM==WINDOWS statement block 2; #else statement block 3; #endif
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.
Macro | Description |
---|---|
__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 |