- 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
Macros in C
Macros in C are the names given to specific constant values or code statements which are replaced with their value/code before the compilation processor. C Macros are defined using the #define preprocessor directive.
Macros are useful for code reusability, defining constant values, defining inline functions, and conditional compilations.
The following are the different types of C macros that we are going to cover in this tutorial –
- Object-like Macros
- Function-like Macros
- Chained Macros
- Variadic Macros
- Predefined Macros
Object-like Macros
A macro that defines a constant is an object-like macro.
Syntax
It is done with the following syntax −
#define name value
Example of Object-like Macros
In the following example, we are defining an object-like macro −
#include <stdio.h> // Defining macros #define PI 3.14 #define MAX 10 int main() { // Printing the values printf("Value of PI = %d\n", PI); printf("Value of MAX = %d\n", MAX); return 0; }
Function-like Macro
To define a function-like macro, you use the same "#define" directive, but you put a pair of parentheses immediately after the macro name, with one or more arguments. Such a macro is expanded only when its name appears with a pair of parentheses after it.
When the preprocessor expands such a macro, it incorporates the specified arguments in the replacement text. The function-like macros are often called Macros with parameters (or arguments).
Syntax
A function-like macro is defined as follows −
#define macro_name([parameter_list]) replacement_text
Example of Function-like Macros
An example of function-like macro is given below −
#include <stdio.h> #define square(x) ((x) * (x)) int main(){ int x = 5; printf("x: %d \tSquare of x: %d", x, square(x)); return 0; }
Output
When you run this code, it will produce the following output −
x: 5 Square of x: 25
Rules for Defining Function-like Macros
Some rules of defining a function also apply to macros −
- A macro can be defined without arguments
- A macro can be defined with a fixed number of arguments
- A macro can be defined with a variable number of arguments
For example, when you use such a macro, the comma-separated argument list must contain as many arguments as there are parameters in the macro definition.
Function-like Macros without Arguments
A function-like macro may also be defined without arguments.
Example 1
The following example shows how you can use a macro without arguments −
#include <stdio.h> #define MESSAGE() printf("Hello World"); int main() { int x = 5; MESSAGE(); return 0; }
Output
Run the code and check its output −
Hello World
Some standard libraries also provide macro definitions in it. For example, the getchar() macro when expanded, implements the getc() function as follows −
#define getchar() getc(stdin)
Similarly, the putchar() macro encapsulates the putc() function −
#define putchar(x) putc(x, stdout)
Example 2
The following program defines a macro named as LOOP(x) and runs a for loop for the number of times as its argument −
#include <stdio.h> #define LOOP(x) {\ for (int i = 1; i <= x; i++)\ printf("Iteration no: %d\n", i);\ } int main() { int x = 3; LOOP(x); }
Output
When you run this code, it will produce the following output −
Iteration no: 1 Iteration no: 2 Iteration no: 3
Chained Macros
When we have a macro nested inside another macro, they are called Chained Macros.
Example of Chained Macros
The following example shows how you can use chained macros −
#include <stdio.h> #define PI 3.142 #define CIRCUMFERENCE(x) (2*PI*x) int main(){ int x = 5; printf("Circumference of a circle with radius %d is %f", x, CIRCUMFERENCE(x)); return 0; }
Output
When you run this code, it will produce the following output −
Circumference of a circle with radius 5 is 31.420000
Variadic Macros
You can also define a macro with variable number of arguments or variadic macros. A macro with variable-length argument is a feature that enables a macro to accept any number of arguments. You can pass positional as well as keyword arguments to a macro.
When a variadic macro is defined, the ellipsis (…) is given as an argument to capture variable number of arguments. To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears.
The __VA_ARGS__ is replaced by all of the arguments that match the ellipsis, including commas between them. Note that the variadic macros can be used only in the C99 compatible C compilers and above.
Example of Variadic Macros
Take a look at the following example −
#include <stdio.h> #define MAX_ARGS 5 // Define maximum number of allowed arguments #define ARGS(x, ...) do {\ printf("%d\n", ##__VA_ARGS__); \ } while (0) int main() { ARGS(1, 2, 3); // 3 arguments ARGS(1, 2, 3, 4, 5, 6); // 6 arguments return 0; }
Output
Run the code and check its output −
2 2
Predefined Macros
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
The following example demonstrates how you can use the predefined macros in a C program −
#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: 20:12:19 Line: 8 ANSI: 1