In this tutorial we intend to cover the basics of these two concepts along with working code samples.

1. The Concept of C Macros

Macros are generally used to define constant values that are being used repeatedly in program. Macros can even accept arguments and such macros are known as function-like macros. It can be useful if tokens are concatenated into code to simplify some complex declarations. Macros provide text replacement functionality at pre-processing time.

Here is an example of a simple macro :

#define MAX_SIZE 10

The above macro (MAX_SIZE) has a value of 10.

Now let’s see an example through which we will confirm that macros are replaced by their values at pre-processing time. Here is a C program :

Now lets compile it with the flag -save-temps so that pre-processing output (a file with extension .i ) is produced along with final executable :

$ gcc -Wall -save-temps macro.c -o macro

The command above will produce all the intermediate files in the gcc compilation process. One of these files will be macro.i. This is the file of our interest. If you open this file and get to the bottom of this file :

So you see that the macro MAX_SIZE was replaced with it’s value (10) in preprocessing stage of the compilation process.

Macros are handled by the pre-compiler, and are thus guaranteed to be inlined. Macros are used for short operations and it avoids function call overhead. It can be used if any short operation is being done in program repeatedly. Function-like macros are very beneficial when the same block of code needs to be executed multiple times.

Here are some examples that define macros for swapping numbers, square of numbers, logging function, etc.

Here, TRACE_LOG is the macro defined. First, character string is logged by TRACE_LOG macro, then multiple arguments of different types are also logged as shown in second call of TRACE_LOG macro. Variable arguments are supported with the use of “…” in input argument of macro and ##args in input argument of macro value.

2. C Conditional Macros

Conditional macros are very useful to apply conditions. Code snippets are guarded with a condition checking if a certain macro is defined or not. They are very helpful in large project having code segregated as per releases of project. If some part of code needs to be executed for release 1 of project and some other part of code needs to be executed for release 2, then it can be easily achieved through conditional macros.

Here, we can see that “commented code 1”, “commented code 2” are not printed because these lines of code are commented under #if 0 macro. And, TEST1 macro is defined so, string “MACRO TEST1 is defined” is printed and since macro TEST3 is not defined, so “MACRO TEST3 is defined” is not printed.

2. The Concept of C Inline Functions

Inline functions are those functions whose definition is small and can be substituted at the place where its function call is made. Basically they are inlined with its function call.

Even there is no guarantee that the function will actually be inlined. Compiler interprets the inline keyword as a mere hint or request to substitute the code of function into its function call. Usually people say that having an inline function increases performance by saving time of function call overhead (i.e. passing arguments variables, return address, return value, stack mantle and its dismantle, etc.) but whether an inline function serves your purpose in a positive or in a negative way depends purely on your code design and is largely debatable.

Compiler does inlining for performing optimizations. If compiler optimization has been disabled, then inline functions would not serve their purpose and their function call would not be replaced by their function definition.

To have GCC inline your function regardless of optimization level, declare the function with the “always_inline” attribute:

void func_test() __attribute__((always_inline));

Inline functions provides following advantages over macros.

Since they are functions so type of arguments is checked by the compiler whether they are correct or not.

There is no risk if called multiple times. But there is risk in macros which can be dangerous when the argument is an expression.

They can include multiple lines of code without trailing backlashes.

Inline functions have their own scope for variables and they can return a value.

Debugging code is easy in case of Inline functions as compared to macros.

It is a common misconception that inlining always equals faster code. If there are many lines in inline function or there are more function calls, then inlining can cause wastage of space.

Now, we will understand how inline functions are defined. It is very simple. Only, we need to specify “inline” keyword in its definition. Once you specify “inline” keyword in its definition, it request compiler to do optimizations for this function to save time by avoiding function call overhead. Whenever calling to inline function is made, function call would be replaced by definition of inline function.

About The Geek Stuff

My name is Ramesh Natarajan. I will be posting instruction guides, how-to, troubleshooting tips and tricks on Linux, database, hardware, security and web. My focus is to write articles that will either teach you or help you resolve a problem. Read more about Ramesh Natarajan and the blog.