## DEV Community

Kshitij Srivastava

Posted on • Updated on

# Saving Magic for Macros

We often find ourselves in the middle of writing a function that we cannot bring ourselves to simplify further. The ones which end up relying on some kind of inexplicable "magic" that cannot be abstracted away.

Instead of writing these as functions, consider using macros instead. Let me give you a taste of what they are capable of.

Macros are defined using the `#define` directive and are effectively a copy-paste replacement where they are used with appropriate parameter substitutions.

``````#include <stdio.h>

#define PRINT_MESSAGE(message) printf("%s\n", (message))

int main(void) {
PRINT_MESSAGE("Hello, world!");
return 0;
}
``````

Macros are incredibly powerful since they accept any token as a parameter. So, you could potentially also do this.

``````#define PERFORM_OPERATION(number_1, number_2, operator) \
((number_1) operator (number_2))

int main(void) {
int a = PERFORM_OPERATION(1, 2, +);  // 3
int b = PERFORM_OPERATION(1, 2, -);  // -1
int c = PERFORM_OPERATION(5, 2, *);  // 10
int c = PERFORM_OPERATION(4, 2, /);  // 2

return 0;
}
``````

But, my personal favourite use of macros is to create generic versions of certain often used procedures. Here's one that is used to swap two values of any given data type.

``````#include <stdbool.h>
#include <stdlib.h>

#define SWAP(value_1, value_2, type)\
do\
{\
type* temp = malloc(sizeof(type));\
*temp = value_1;\
value_1 = value_2;\
value_2 = *temp;\
free(temp);\
}\
while (false)
``````

Let me try to explain the weirdness. Since we're creating a variable and since macros are effectively a copy-paste substitution, we have to limit the variable's scope. So, we can place it in a separate block like this do-while block that only executes once.

This function would have been a pain to write normally since there is no direct way to pass the data-type to a function in C. In situations like this, it is often much easier to write a simple macro than to create multiple long and similar functions.

Paul J. Lucas • Edited

There is no reason to use `malloc` in your `SWAP` example:

``````type temp = value_1;
value_1 = value_2;
value_2 = temp;
``````

Using the `do`...`while` loop is not only for scope, but also to ensure it's treated as a single statement:

``````if ( some_condition )
SWAP( a, b );
``````

That code would break if it were not inside a `do`...`while`.

Anyway, you barely scratched the surface regarding macros. For example, you never explain why you use `\` at the end of lines. See here.

Kshitij Srivastava

You are correct about the nature of `do`...`while`, my bad for forgetting to mention its other purpose. This post is just meant as a taste of what macros can do, not necessarily a guide or even best practice.

Paul J. Lucas

The problem with "taste" articles is: unless you explicitly say the article is only a taste, the reader has no idea there's more to learn.