- C Programming Tutorial
- C - Home
- Basics of C
- C - Overview
- C - Features
- C - History
- C - Environment Setup
- C - Program Structure
- C - Hello World
- C - Compilation Process
- C - Comments
- C - Tokens
- C - Keywords
- C - Identifiers
- C - User Input
- C - Basic Syntax
- C - Data Types
- C - Variables
- C - Integer Promotions
- C - Type Conversion
- C - Type Casting
- C - Booleans
- Constants and Literals in C
- C - Constants
- C - Literals
- C - Escape sequences
- C - Format Specifiers
- Operators in C
- C - Operators
- C - Arithmetic Operators
- C - Relational Operators
- C - Logical Operators
- C - Bitwise Operators
- C - Assignment Operators
- C - Unary Operators
- C - Increment and Decrement Operators
- C - Ternary Operator
- C - sizeof Operator
- C - Operator Precedence
- C - Misc Operators
- Decision Making in C
- C - Decision Making
- C - if statement
- C - if...else statement
- C - nested if statements
- C - switch statement
- C - nested switch statements
- Loops in C
- C - Loops
- C - While loop
- C - For loop
- C - Do...while loop
- C - Nested loop
- C - Infinite loop
- C - Break Statement
- C - Continue Statement
- C - goto Statement
- Functions in C
- C - Functions
- C - Main Function
- C - Function call by Value
- C - Function call by reference
- C - Nested Functions
- C - Variadic Functions
- C - User-Defined Functions
- C - Callback Function
- C - Return Statement
- C - Recursion
- Scope Rules in C
- C - Scope Rules
- C - Static Variables
- C - Global Variables
- Arrays in C
- C - Arrays
- C - Properties of Array
- C - Multi-Dimensional Arrays
- C - Passing Arrays to Function
- C - Return Array from Function
- C - Variable Length Arrays
- Pointers in C
- C - Pointers
- C - Pointers and Arrays
- C - Applications of Pointers
- C - Pointer Arithmetics
- C - Array of Pointers
- C - Pointer to Pointer
- C - Passing Pointers to Functions
- C - Return Pointer from Functions
- C - Function Pointers
- C - Pointer to an Array
- C - Pointers to Structures
- C - Chain of Pointers
- C - Pointer vs Array
- C - Character Pointers and Functions
- C - NULL Pointer
- C - void Pointer
- C - Dangling Pointers
- C - Dereference Pointer
- C - Near, Far and Huge Pointers
- C - Initialization of Pointer Arrays
- C - Pointers vs. Multi-dimensional Arrays
- Strings in C
- C - Strings
- C - Array of Strings
- C - Special Characters
- C Structures and Unions
- C - Structures
- C - Structures and Functions
- C - Arrays of Structures
- C - Self-Referential Structures
- C - Lookup Tables
- C - Dot (.) Operator
- C - Enumeration (or enum)
- C - Structure Padding and Packing
- C - Nested Structures
- C - Anonymous Structure and Union
- C - Unions
- C - Bit Fields
- C - Typedef
- File Handling in C
- C - Input & Output
- C - File I/O (File Handling)
- C Preprocessors
- C - Preprocessors
- C - Pragmas
- C - Preprocessor Operators
- C - Macros
- C - Header Files
- Memory Management in C
- C - Memory Management
- C - Memory Address
- C - Storage Classes
- Miscellaneous Topics
- C - Error Handling
- C - Variable Arguments
- C - Command Execution
- C - Math Functions
- C - Static Keyword
- C - Random Number Generation
- C - Command Line Arguments
- C Programming Resources
- C - Questions & Answers
- C - Quick Guide
- C - Cheat Sheet
- C - Useful Resources
- C - Discussion
Preprocessors in C
The C Preprocessor is not a part of the compiler, but is a separate step in the compilation process. In simple terms, a C Preprocessor is just a text substitution tool and it instructs the compiler to do the required pre-processing before the actual compilation. We'll refer to the C Preprocessor as CPP.
In C programming, preprocessing is the first step in the compilation of a C code. It occurs before the tokenization step. One of the important functions of a preprocessor is to include the header files that contain the library functions used in the program. The preprocessor in C also defines the constants and expands the macros.
The preprocessor statements in C are called directives. A preprocessor section of the program always appears at the top of the C code. Each preprocessor statement starts with the hash (#) symbol.
Preprocessor Directives in C
The following table lists down all the important preprocessor directives −
Directive | Description |
---|---|
# define | Substitutes a preprocessor macro. |
#include | Inserts a particular header from another file. |
#undef | Undefines a preprocessor macro. |
#ifdef | Returns true if this macro is defined. |
#ifndef | Returns true if this macro is not defined. |
#if | Tests if a compile time condition is true. |
#else | The alternative for #if. |
#elif | #else and #if in one statement. |
#endif | Ends preprocessor conditional. |
#error | Prints error message on stderr. |
#pragma | Issues special commands to the compiler, using a standardized method. |
Preprocessors Examples
Analyze the following examples to understand various directives.
This #define directive tells the CPP to replace the instances of MAX_ARRAY_LENGTH with 20. Use #define for constants to increase readability.
#define MAX_ARRAY_LENGTH 20
The following directives tell the CPP to get "stdio.h" from the System Libraries and add the text to the current source file. The next line tells CPP to get "myheader.h" from the local directory and add the content to the current source file.
#include <stdio.h> #include "myheader.h"
Now, take a look at the following #define and #undef directives. They tell the CPP to undefine existing FILE_SIZE and define it as 42.
#undef FILE_SIZE #define FILE_SIZE 42
The following directive tells the CPP to define MESSAGE only if MESSAGE isn't already defined.
#ifndef MESSAGE #define MESSAGE "You wish!" #endif
The following directive tells the CPP to process the statements enclosed if DEBUG is defined.
#ifdef DEBUG /* Your debugging statements here */ #endif
This is useful if you pass the -DDEBUG flag to the gcc compiler at the time of compilation. This will define DEBUG, so you can turn debugging ON and OFF on the fly during compilation.
Predefined Macros in C
ANSI C defines a number of macros. Although each one is available for use in programming, the predefined macros should not be directly modified.
Macro | Description |
---|---|
__DATE__ | The current date as a character literal in "MMM DD YYYY" format. |
__TIME__ | The current time as a character literal in "HH:MM:SS" format. |
__FILE__ | This contains the current filename as a string literal. |
__LINE__ | This contains the current line number as a decimal constant. |
__STDC__ | Defined as 1 when the compiler complies with the ANSI standard. |
Example
Let's try the following example −
#include <stdio.h> int main(){ printf("File: %s\n", __FILE__ ); printf("Date: %s\n", __DATE__ ); printf("Time: %s\n", __TIME__ ); printf("Line: %d\n", __LINE__ ); printf("ANSI: %d\n", __STDC__ ); }
Output
When you run this code, it will produce the following output −
File: main.c Date: Mar 6 2024 Time: 13:32:30 Line: 8 ANSI: 1
Preprocessor Operators
The C preprocessor offers the following operators to help create macros −
Example: The Macro Continuation (\) Operator in C
A macro is normally confined to a single line. The macro continuation operator (\) is used to continue a macro that is too long for a single line. Take a look at the following example −
#include <stdio.h> #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") int main() { message_for(Ram, Raju); }
Output
When you run this code, it will produce the following output −
Ram and Raju: We love you!
Example: The Stringize (#) Operator in C
The stringize operator (#), also called number-sign operator, when used within a macro definition, converts a macro parameter into a string constant.
The stringize operator may be used only in a macro having a specified argument or parameter list. For example −
#include <stdio.h> #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") int main() { message_for(Carole, Debra); return 0; }
Output
Run the code and check its output −
Carole and Debra: We love you!
Example: The Token Pasting (##) Operator in C
The token-pasting operator (##) within a macro definition combines two arguments. It permits two separate tokens in the macro definition to be joined into a single token. For example −
#include <stdio.h> #define tokenpaster(n) printf ("token" #n " = %d", token##n) int main() { int token34 = 40; tokenpaster(34); return 0; }
Output
When you run this code, it will produce the following output −
token34 = 40
Example: The defined() Operator in C
The preprocessor defined operator is used in constant expressions to determine if an identifier is defined using #define. If the specified identifier is defined, the value is true (non-zero). If the symbol is not defined, the value is false (zero).
The following example shows how you can use the defined operator in a C program −
#include <stdio.h> #if !defined (MESSAGE) #define MESSAGE "You wish!" #endif int main() { printf("Here is the message: %s\n", MESSAGE); return 0; }
Output
Run the code and check its output −
Here is the message: You wish!
Parameterized Macros in C
One of the powerful functions of the CPP is the ability to simulate functions using parameterized macros. For example, we might have some code to square a number as follows −
int square(int x) { return x * x; }
We can rewrite above the code using a macro as follows −
#define square(x) ((x) * (x))
Macros with arguments must be defined using the #define directive before they can be used. The argument list is enclosed in parentheses and must immediately follow the macro name. Spaces are not allowed between the macro name and open parenthesis.
Example
The following example demonstrates how you can use parameterized macros in C −
#include <stdio.h> #define MAX(x,y) ((x) > (y) ? (x) : (y)) int main() { printf("Max between 20 and 10 is %d\n", MAX(10, 20)); return 0; }
Output
When you run this code, it will produce the following output −
Max between 20 and 10 is 20