This article is the continuation of the Series on the C programming tutorial and carries the discussion on C language programming and its implementation. It aims to provide easy and practical examples for understanding the C program. In our last article, we have seen the Functions in C programming. In this article, we are going to explain Preprocessor in C Programming.
Preprocessor in C Programming
What is a preprocessor in C?
In C programming, a preprocessor is a tool that performs text preprocessing before the compilation of the source code. It is a separate step in the compilation process that is responsible for manipulating the source code before it is passed to the compiler. There are multiple process is happening during the compilation. We have discussed those things in this article already. Please check that.
The preprocessor directives in C start with a hash symbol (#) and are processed by the preprocessor. These directives are used to include header files, define macros, and perform conditional compilation.
The preprocessor plays a crucial role in C programming by allowing developers to create modular and reusable code, customize the behavior of the compiler, and enable conditional compilation based on different requirements.
What is the use of a preprocessor in C programming?
A preprocessor in C programming is a tool that processes source code before it is compiled. It performs tasks such as including header files, defining constants, and performing macro expansion. It helps in making code more modular and efficient.
To instruct the preprocessor you have to use the preprocessor Directive which lets you compile the code depending on some conditional command.
What is the List of preprocessor Directives available?
There are many preprocessor Directives available. Some of them are,
- #include: It inserts a header file from another file.
- #define: It is a preprocessor used as a macro.
- #undef: It undefines a preprocessor macro.
- #if: Tests if a compile-time condition is true.
- #ifdef: Return true if the macro is defined.
- #ifndef: Return true if the macro is not defined.
- #else: The alternative for #if.
- #elif: else and #if in one statement.
- #endif: Ends preprocessor conditional.
- #warning: It can be used for warnings.
- #error: It is used to stop compilation.
How many types of preprocessor Directives?
There are four types of preprocessors given below.
File Inclusion
File inclusion preprocessor command (#include
) tells the compiler to include a file in the source code program. Generally, two types of files are included in the program.
Why do use file inclusion?
- When we want to maintain the modularized code, we need to create multiple source files. In that case, we may need to include the other files in any of the source code.
- There are many libraries available. For example string. If we want to use the string functions, we can include the string.h file (
#include string.h
) and we can use the functions available in that file.
Types of header files
- Standard/Pre-define header file (
#include <file_name.h>
) - User-defined header file (
#include "file_name.h"
)
Standard/Pre-define header file
It contains definitions of pre-defined functions that have been developed and are already available like stdio.h
, string.h
etc. If you #include
with <angular brackets>
it means that your operating system will be searching for the particular pre-define location like SDK or PATH.
Syntax
// Compiler look for the file in specified list of directories only #include <filename.h>
Example
#include <stdio.h> #include <string.h> int main() { char str[50]; printf("Enter String:- "); gets(str); puts(str); return 0; }
In this above program, I have used two files of the standard header file (stdio.h, string.h) which is readily available already. So we don’t have to create it on our own.
Output
Enter String:- EmbeTronicX EmbeTronicX
User-defined header file
It contains definitions of user-defined functions that have been created by us and included in the program like “my_header.h” etc. If you #include
with "double quotes"
it means that your operating system will be searching for both the user project location which is inside the source file as well as a particular pre-define location which is inside the standard library files.
// Compiler look for the file in current directory as well as specified list of directories #include "file_name.h"
Example
main.c file
#include <stdio.h> #include "my_fun.h" int main() { int a,b,c; printf("Enter two numbers:- "); scanf("%d%d",&a,&b); c=add(a,b); printf("%d + %d = %d",a,b,c); return 0; }
my_fun.h file
int add(int a, int b) { return (a+b); }
Output
Enter two numbers:- 5 2 5 + 2 = 7
Macros in C Programming
Macros
In C programming, a macro is a way to define a piece of code that can be reused throughout the program. It is a preprocessor directive that allows you to define constants, functions, or code snippets that can be easily substituted wherever they are called. Macros are defined using the #define
directive and can help in simplifying complex code, improving readability, and reducing code duplication. When the program is compiled, the macro statements are replaced by their corresponding value or code. Overall, macros are a powerful tool for writing flexible and efficient code in C programming.
Note: While Declaring the MACRO the characters should always be used in uppercase and you should not use semicolon at the end while defining the macro statement in a program, it will be a good programming practice.
Example
#include <stdio.h> #define AREA(r) (3.1415 * r * r) int main() { float r,a; printf("Enter a radius:- "); scanf("%f",&r); a=AREA(r); printf("Area = %.1f",a); return 0; }
In this above program, I have defined a macro called AREA
. I’m reusing it in the code.
Output
Enter a radius:- 5 Area = 78.5
What is macro with an argument?
Whenever you convert a function with macro then that is called macro with argument, It is good to be used for a small program to define macro rather than use it for a big program. There is another example 2 in which you can declare the whole C statement in macro, given below.
Syntax
#define CUBE(n) n*n // (Cube---> Macro, (n)---> Macro Declartion, n*n---> Macro Defination)
Example 1
#include <stdio.h> #define CUBE(n) (n*n) int main() { int i,n; printf("Enter a number:- "); scanf("%d",&n); i=CUBE(n); printf("Cube = %d",i); return 0; }
Output
Enter a number:- 5 Cube = 25
Example 2
#include <stdio.h> #define DECISION (a>50 && a<100) #define DISPLAY_1 printf("Greater then 50") #define DISPLAY_2 printf("Less then 50") int main() { int a; printf("Enter a Number:- "); scanf("%d",&a); if(DECISION) { DISPLAY_1; } else { DISPLAY_2; } }
In the above program, we have declared three macros (DECISION
, DISPLAY_1
, DISPLAY_2
). Display macros used to print different prints. DECISION
macro checks for the condition.
Output
Enter a Number:- 70 Greater then 50
Enter a Number:- 20 Less then 50
Multiline Macro in C
In C, macros are often used to define reusable code snippets. While most macros consist of a single line of code, it is also possible to create multiline macros. This can be achieved using the \
character to indicate that the macro continues onto the next line. Here’s an example:
#include <stdio.h> #define PRINT_VALUES(a, b) \ printf("Value of a: %d\n", a); \ printf("Value of b: %d\n", b); int main() { int x = 5; int y = 10; PRINT_VALUES(x, y); return 0; }
In this example, we have defined a multiline macro called PRINT_VALUES
that takes two arguments a
and b
. The macro is used to print the values of these arguments using printf
statements. The \
character at the end of each line indicates that the macro continues onto the next line.
When the code is compiled and executed, the output will be:
Value of a: 5 Value of b: 10
Note that the use of multiline macros can be helpful in reducing code duplication and improving code readability. However, it’s important to use them judiciously and consider their impact on the code’s maintainability.
Macro vs Function
In C programming, macros, and functions are both important tools that serve different purposes. Here’s a brief comparison between macros and functions:
Macro | Function |
Macros in C are defined using the #define preprocessor directive. | Functions in C are defined using the function_name() format and can take parameters and return values. |
Macros are used to define constant values or to define code snippets that need to be expanded inline. | Functions are a fundamental part of C programming and are used to modularize code and improve code readability. |
Macros are not type-safe and do not perform any kind of argument type checking. | Functions provide type safety as the compiler can perform argument type checking. |
Macros are expanded by the preprocessor before compilation, replacing the macro code with the corresponding definition. | Functions are called at runtime and have a separate memory location for each invocation. |
Macros have the advantage of being able to perform complex operations at compile-time, such as string concatenation or conditional compilation. | Functions are generally more efficient than macros in terms of code size, especially for large and complex code blocks. |
Macros can result in larger code size as they are copied wherever they are used. | Functions are useful for implementing reusable code and promoting code reusability. |
Example: #define ADD(a,b) a+b | Example: int add(int a, int b) |
Overall, macros and functions each have their own advantages and use cases. Choosing between them largely depends on the specific requirements and goals of your program.
Macro vs inline functions in C
In our next article, we will see the difference between macro and inline functions. in C programming.
Conditional Compilation in C Programming
Conditional compilation in C programming is a powerful feature that allows developers to selectively compile specific sections of code based on certain conditions. This feature is particularly useful when dealing with code that needs to work on different platforms, with variations in operating systems, hardware configurations, or compiler-specific directives.
What are the types of preprocessors used in conditional compilation?
These are the preprocessor directives, commonly used for conditional compilation in C programming.
#if
In C programming, the #if
directive is part of the preprocessor directives used for conditional compilation. It tests whether a compile-time condition is true and determines whether the code within the corresponding block should be included during the compilation process.
The #if
directive is often used in conjunction with other conditional directives such as #ifdef
, #ifndef
, #else
, and #elif
to create multiple branches of code execution based on different conditions.
Here is an example to illustrate the usage of #if
:
#include <stdio.h> #define NUMBER 10 int main() { #if NUMBER < 5 printf("Number is less than 5.\n"); #endif return 0; }
In this example, the NUMBER
macro is defined as 10. The #if
directive is used to test the condition NUMBER < 5
and determine which branch of code should be included during compilation. Since the condition is false, the code between the NUMBER < 5
and #endif
is not included during the compilation.
The #if
directive allows you to create logic branches in your code based on compile-time conditions, making your program more flexible and adaptable to different scenarios.
#endif
This directive marks the end of a conditional block. This should be used only with any of the below preprocessor directives.
#ifdef
This directive checks whether a macro or symbol is defined. If the specified macro or symbol is defined, the code between #ifdef
and #endif
will be included during the compilation process. Otherwise, it will be skipped.
#include <stdio.h> #define DEBUG int main() { #ifdef DEBUG printf("Debug mode enabled."); #endif return 0; }
In the above program, printf("Debug mode enabled.")
will be compiled only if the DEBUG
macro is defined. So, the DEBUG
macro is defined in the above program. So, that printf will be compiled.
#ifndef
This directive is the opposite of #ifdef
. It checks whether a macro or symbol is not defined. If the specified macro or symbol is not defined, the code between #ifndef
and #endif
will be included during the compilation.
#include <stdio.h> #define DEBUG int main() { #ifndef DEBUG printf("Debug mode is not enabled."); #endif return 0; }
In the above program, printf("Debug mode is not enabled.")
will be compiled only if the DEBUG
macro is not defined. So, the DEBUG
macro is defined in the above program. So, that printf will not be compiled.
#else
This directive is used in conjunction with #ifdef
or #ifndef
. If the condition specified by #ifdef
or #ifndef
evaluates to false
, the code between #else
and #endif
will be included instead.
#include <stdio.h> #define DEBUG int main() { #ifdef DEBUG printf("Debug mode enabled."); #else printf("Debug mode disabled."); #endif return 0; }
In this example, when the DEBUG
macro is defined, the code between #ifdef DEBUG
and #else
will be included during compilation, and the output will be “Debug mode enabled.” Conversely, if the DEBUG
macro is not defined, the code between #else
and #endif
will be included, and the output will be “Debug mode disabled.“
#elif
This #elif
directive is used in conjunction with conditional compilation to create multiple branches of code execution based on different conditions. It stands for “else if
” and is often used in combination with #ifdef
, #ifndef
, and #else
.
The #elif
directive allows you to specify an additional condition to be checked if the previous condition specified by #if
or #elif
is false. If the additional condition evaluates to true, the code block following #elif
will be included during the compilation. If the additional condition is false, the compiler will move on to the next #elif
or #else
directive.
Here’s an example to illustrate the usage of #elif
:
#include <stdio.h> #define NUMBER 10 int main() { #if NUMBER < 5 printf("Number is less than 5.\n"); #elif NUMBER > 5 && NUMBER < 10 printf("Number is greater than 5 and less than 10.\n"); #else printf("Number is either less than or equal to 5, or greater than or equal to 10.\n"); #endif return 0; }
In this example, the value of the NUMBER
macro is 10
. The first condition NUMBER < 5
is false, so the compiler moves on to the next #elif
directive. The second condition NUMBER > 5 && NUMBER < 10
is true, so the code block following #elif
is executed, and the output will be “Number is greater than 5 and less than 10.“
The #elif
directive allows you to create multiple conditions and branches of code, making your program more flexible and adaptable to different scenarios.
#if defined
In C programming, the #if defined
directive is used for conditional compilation based on the existence of a specific macro or symbol in the code. The #if defined
directive is often used in conjunction with other conditional directives such as #ifdef
, #ifndef
, #else
, and #elif
to selectively compile different sections of code based on the presence or absence of a macro or symbol.
Here’s the syntax of the #if defined
directive:
#if defined(MACRO_NAME) // code to be compiled if the macro is defined #else // code to be compiled if the macro is not defined #endif
The defined
keyword is used to test whether a macro or symbol is defined. If the specified macro or symbol is defined, the code between #if defined
and #else
will be included during the compilation process. Otherwise, the code between #else
and #endif
will be included.
Here’s an example to illustrate the usage of #if defined
:
#include <stdio.h> #define DEBUG int main() { #if defined(DEBUG) printf("Debug mode enabled.\n"); #else printf("Debug mode disabled.\n"); #endif return 0; }
In this example, the DEBUG
macro is defined using the #define
directive. The #if defined(DEBUG)
directive checks whether the DEBUG
macro is defined. Since it is defined, the code between #if defined(DEBUG)
and #else
will be compiled, and the output will be “Debug mode enabled.“
If the DEBUG
macro is not defined, the code between #else
and #endif
will be compiled, and the output will be “Debug mode disabled.“
The #if defined
directive allows you to create different branches of code execution based on the existence of specific macros or symbols, making your program more flexible and adaptable to different scenarios.
What is the difference between #ifdef and #if defined?
#ifdef
and #if defined
are both preprocessor directives in the C programming languages that are used for conditional compilation. While they serve a similar purpose, there is a slight difference between them.
The #ifdef
directive checks if a macro or identifier is defined, and if it is, the code within the #ifdef
block is compiled. On the other hand, the #if defined
directive is used to evaluate a condition based on whether a macro or identifier is defined, and if the condition is true, the code within the #if defined
block is compiled.
In practical terms, the only difference is in the syntax. With #ifdef
, you only need to specify the macro or identifier directly after it, like this:
#ifdef MACRO_NAME // Code to be compiled if MACRO_NAME is defined #endif
With #if defined
, you need to use the defined
operator along with the macro or identifier you want to check, like this:
#if defined(MACRO_NAME) // Code to be compiled if MACRO_NAME is defined #endif
Both directives offer conditional compilation based on the status of macros or identifiers, allowing you to selectively include or exclude code sections during the compilation process. Choose the one that best fits your preference and coding style.
When using #if defined
, you can combine multiple conditions using logical operators such as &&
(AND) and ||
(OR).
Here’s an example to demonstrate the usage of logical operators in #if defined
:
#include <stdio.h> #define DEBUG #define TESTING int main() { #if defined(DEBUG) && defined(TESTING) printf("Debug mode enabled and testing is in progress.\n"); #elif defined(DEBUG) || defined(TESTING) printf("Debug mode enabled or testing is in progress.\n"); #else printf("Neither debug mode nor testing is active.\n"); #endif return 0; }
In this example, the DEBUG
and TESTING
macros are defined using the #define
directive. The #if defined(DEBUG) && defined(TESTING)
condition checks if both DEBUG
and TESTING
macros are defined, and if the condition is true, the code between #if
and #elif
is compiled. The output will be “Debug mode enabled and testing is in progress.“
If either DEBUG
or TESTING
macro is defined, the #if defined(DEBUG) || defined(TESTING)
condition will be true, and the code between #elif
and #else
will be compiled. The output will be “Debug mode enabled or testing is in progress.“
If neither DEBUG
nor TESTING
macro is defined, the code between #else
and #endif
will be compiled, and the output will be “Neither debug mode nor testing is active.“
By using logical operators in conjunction with #if defined
, you can create more complex conditions for conditional compilation based on the existence of multiple macros or identifiers.
Conditional compilation can be extremely useful in many scenarios. For example, you can use it to include platform-specific code, define feature flags, or enable debugging statements in development builds while excluding them in production builds. Conditional compilation allows developers to write flexible and customized code for different scenarios without cluttering the codebase with unnecessary statements. It enhances code readability, maintainability, and portability.
Miscellaneous Preprocessor Directives
Miscellaneous Directives are two types and they are not commonly used in the program.
#undef
The #undef
directive in C is used to undefine a defined macro. It is commonly used to remove preprocessor definitions or macros that were previously defined using the #define
directive.
Here is an example:
#include <stdio.h> #define PI 3.14159 int main() { printf("The value of PI: %f\n", PI); #undef PI printf("After undefining PI:\n"); printf("The value of PI: %f\n", PI); // This will cause a compilation error return 0; }
In the above example, we define the macro PI
with a value of 3.14159
. After that, we use the #undef
directive to remove the definition of PI
. Therefore, when we try to access PI
again, it will result in a compilation error because it is no longer defined.
#pragma
In C programming, #pragma
is a preprocessor directive that provides specific instructions to the compiler. It is used to enable or disable specific features, control optimization settings, or provide additional information to the compiler.
Here are a few common uses of #pragma
in C:
- Pragma Once: This directive ensures that a header file is included only once in a source file, even if it is included multiple times. It helps prevent multiple definitions of variables, types, or functions.
#pragma once // Header file content
- Pragma Message: This directive allows you to display custom warnings or informational messages during compilation. It can be useful for debugging or providing instructions to the developers.
#pragma message "Compiling custom message..." // Rest of the code
- Pragma Pack: This directive controls the alignment and padding of structure members. It specifies the byte alignment for subsequent structure declarations.
#pragma pack(push, 1) struct MyStructure { // Structure members }; #pragma pack(pop) // Rest of the code
- Pragma Inline: This directive suggests the compiler to inline a function, which means inserting the function’s code at each calling site, instead of invoking it as a separate function. It can improve performance in certain cases.
#pragma inline int add(int a, int b) { return a + b; } // Rest of the code
Please note that the specific behavior and availability of #pragma
directives may vary depending on the compiler you are using.
#error
#error
is a preprocessor directive in C programming that generates a compilation error with a specified error message. This directive is typically used to provide informative error messages during the compilation process. When the compiler encounters #error
, it terminates the compilation and displays the specified error message.
Here’s an example:
#if defined(WIN32) // Windows-specific code #else #error "This code is only compatible with Windows" #endif
In the above example, #error
is used to generate an error message if the code is being compiled on a non-Windows platform. The compiler will display the error message “This code is only compatible with Windows” and terminate the compilation.
Using #error
can be helpful in ensuring that your code is correctly compiled and executed on the desired platform, and it provides a clear indication of any compatibility issues that may arise.
#warning
The #warning
directive in C is a preprocessor directive that allows you to generate warning messages during compilation. It is often used to display custom warning messages or reminders to developers. When the compiler encounters a #warning
directive, it displays the specified warning message, but it does not stop the compilation process.
Here’s an example of how to use #warning
:
#warning Remember to refactor this code before release. // Rest of the code
In the above example, the #warning
directive is used to display a reminder message to the developers. When the code is compiled, the compiler will display the warning message “Remember to refactor this code before release.“
The #warning
directive can be useful for highlighting areas of code that need attention or improvement, providing guidance to developers, or serving as reminders during the development process. It helps in maintaining code quality and reducing potential issues.
In our next article, we will see the difference between macro and inline functions. in C programming. If you want to read the compilation process in C programming, you can read this article.
You can also read the below tutorials.

Embedded Engineer|| C programming || Microcontroller
Hi. I am Sunil an Electrical Engineer as well as an Embedded Engineer. I had interested in embedded systems to learn things and to implement my working ideas practically on embedded and all their domains. So here you can find my articles which have been created by me in a simple way to make you understand its concepts. I believe that learning things and after that implementing them practically is a good way to gain experience.
Thank you for reading my articles keep supporting and keep learning!