Many programming languages provide macros and functions, each with unique syntax and features. Both of them serve a similar purpose of performing a specific task by creating reusable code.
In this article, we will explore the similarities and differences between macros and functions and discuss the advantages and disadvantages of both.
A macro is a preprocessor directive that defines a piece of reusable code. Macros reduce the repetition of code and increase readability. In C++, we define macros using the #define preprocessor directive. The syntax of a macro definition is as follows:
The Preprocessor removes all occurrences of a macro (and all other preprocessor directives) and replaces it with the macro’s definition, just like it is. For example, any occurrence of MULTIPLY(2, 5) converts to ((2) * (5)) after preprocessing. This property of macros also leads to unexpected results.
Let us look at an example of code before and after preprocessing. This can be done using the g++ -E flag, which runs the preprocessor stage of the compiler. Thus, to run the preprocessor on the main.cpp, you use the g++ -E main.cpp command.
Original Code
#define NUMBER 10
int main() {
int a = NUMBER, b = NUMBER * NUMBER;
return 0;
}
You can also try this code with Online C++ Compiler
In this code, after preprocessing we can see that the compiler replaces all occurrences of the macro NUMBER with its definition 10.
Advantages of Macros
The advantages of macros are:
Macros reduce duplicate code and save our time and effort.
Macros increase readability by defining a simple macro for a complex task.
Macros can enable or disable certain blocks of code and therefore be useful for debugging.
Generally, macros are faster than functions.
Disadvantages of Macros
The disadvantages of macros are:
Macros can sometimes make code difficult to debug if the error occurs within the macro.
Macros don’t do type-checking and thus can sometimes produce unexpected results.
Macros increase the code size after preprocessing.
Macros can lead to unexpected results if not used cautiously.
Uses of Macros
We can use Macros to:
Define constants.
Compile conditionally. We can use this to make platform-specific code, etc.
Generate code based on input conditions. For example, in competitive programming, some people use macros to make for loops smaller. The start and end value of the looping variable is given as arguments to the macro.
#define FOR(start, end, step) for(int i = start; i <= end; i += step)
What is a function?
A function is a block of related statements performing a specific task. Functions allow us to write modular and reusable code, making the code easier to maintain. The syntax of a function definition is as follows:
return_type function_name(parameter list) {
// function body
}
You can also try this code with Online C++ Compiler
The compiler translates functions into machine code and includes them in an executable program, which means functions are compiled and linked at compile time. Let us look at an example of using functions.
Now, Let us look at the complete code.
Implementation
#include <iostream>
using namespace std;
int add(int x, int y) {
return x + y;
}
int main() {
cout << "Sum of 1 and 3 = " << add(1, 3) << '\n';
}
You can also try this code with Online C++ Compiler
This code defines a function add which takes two arguments x and y and returns their sum. The main function calls this add function and outputs its result.
Advantages of Functions
The advantages of functions are:
Functions combine a set of statements performing one function, making code easier to understand and more readable.
Functions reduce duplication of code and allow code reusability.
Functions can be overloaded with different parameter types.
Disadvantages of Functions
The disadvantages of functions are:
It can be difficult to debug a recursive function.
Function calls have an overhead that makes them slower.
Uses of Functions
We can use functions to:
Perform calculations like addition or multiplication. Functions can abstract away complex calculations and make code more readable.
Manipulate data (sorting or filtering).
Handle input/output operations, like handling large files.
Create libraries of code that others can use.
Test the working of the code and debugging.
Define methods on objects.
Macro Vs Function
The following table gives the differences between macros and functions.
Based on
Macro
Function
Type Checking
Macros don’t perform type checking, which means macro will be executed even if you pass arguments with incorrect data type.
Functions perform type checking and give a compilation error if we pass the wrong data type arguments.
Debugging
It is harder to debug code with macros as it is difficult to understand the result of substituting many macros.
It is easier to debug code with functions.
Overloading
We cannot overload macros.
We can overload functions and provide different functionality for different sets of arguments.
Performance
Macros are faster than functions as there is no function call overhead.
Functions are generally slower.
Length
Usually single line. We can write multiline macros using a backslash character at the end of each line.
It can span across any number of lines (no restrictions).
Time of processing
Macros are processed during the preprocessing stage.
Functions are compiled during the compilation stage.
Code length after compilation
Increases.
Remains same.
Use
Macros are helpful for small reusable codes.
Functions are useful for large reusable codes.
Return values
Macros do not return values.
Functions can return values.
Nesting
Macros can be nested.
Functions cannot be nested.
Side-Effects
Macros can have unwanted side effects.
Functions generally don’t have any side effects.
Example
Let's understand the difference using an example.
Implementation
#include <iostream>
using namespace std;
int MUL_FUNC(int x, int y) {
return x * y;
}
#define MUL_MACRO(x, y) x* y
int main() {
cout << MUL_FUNC(1 + 2, 2 + 1) << '\n';
cout << MUL_MACRO(1 + 2, 2 + 1) << '\n';
return 0;
}
You can also try this code with Online C++ Compiler
The function MUL_FUNC is defined using the int keyword and takes two integer parameters, x and y. The function is then called with the arguments (1 + 2, 2 + 1) and returns the value 9.
On the other hand, the macro MUL_MACRO is defined using the #define preprocessor directive and takes two integer parameters, x and y. When the macro is called with the arguments (1 + 2, 2 + 1), it expands to 1 + 2 * 2 + 1, then evaluated as 6.
We should use macros carefully because they lack type checking, variable scope, and other features that make code more reliable and easier to maintain.
Can macros be defined inside functions in C++?
Yes, macros can be defined inside functions in C++, but this is generally not recommended as it reduces readability.
Can we use macros to modify program flow in C++?
Yes, we can use macros to change program flow in C++ using conditional statements such as #ifdef and #ifndef.
Why do we use macros in competitive programming?
We use macros in competitive programming to save typing time and make the code more concise. Macros can be used to define constants and to perform simple operations.
How do macros affect the size of a compiled program?
Macros can increase the size of a compiled program in C++ because they are replaced by the preprocessor before compilation, resulting in duplicated code. This can lead to larger executable files and longer compile time.
Conclusion
This article discussed how macros and functions serve similar functions but differ significantly. The choice between a macro or a function depends on the programmer and the use case.
To learn more about C/C++, we recommend reading the following articles: