Post

[C/C++] User-defined Macro(2): Advanced

[C/C++] User-defined Macro(2): Advanced

Abstract

This post explores advanced macro techniques in C and C++, including stringification (#), token pasting (##), conditional compilation directives, variadic macros, and predefined debugging macros.

1. Introduction

Beyond simple constants and function-like macros, the C preprocessor provides powerful metaprogramming features.
Stringification and token pasting enable dynamic identifier and string creation; conditional directives (#ifdef, #ifndef, #undef) control compilation flow; variadic macros (__VA_ARGS__) support flexible argument lists; and predefined macros (__FILE__, __LINE__, __func__) aid in debugging and diagnostics.

2. Organization

  1. Token Pasting and Stringification# and ## operators
  2. Conditional Compilation#ifdef, #ifndef, #undef
  3. Variadic Macros__VA_ARGS__ and comma-swallowing
  4. Predefined Debugging Macros__FILE__, __LINE__, __func__
  5. Previous — Link to the basic macro features post

3. Sections

3.1. Stringification and Token Pasting

The # operator converts an argument into a string constant as shown below:

Click Run ▶

Simillarly, ## operator pastes token to one identifier.

Click Run ▶

3.2. Conditional Compilation

Macros can also be used for conditional branching using preprocessor directives.

The #ifndef directive means:

“if this identifier has not been defined.”

This allows you to define a macro only if it hasn’t been defined elsewhere–useful to ensuring consistent values across multiple files.

1
2
3
#ifndef PI
#define PI 3.141592
#endif

Simillarly, the #ifdef directive means:

“if this identifier has been defined.”

1
2
3
4
5
#define DEBUG

#ifdef DEBUG
    printf("Debug mode is on.\n");
#endif

To undefine a macro, use the #undef directive:

#undef identifier.

3.3. Variadic Macros

Variadic macros are function-like macros that accept a variable number of arguments.

Click Run ▶

The ...(ellipsis) is replaced by the special identifier __VA_ARGS__, which gets expanded into the variable arguments passed to the macro.

__VA_ARGS__ is especially useful for writing flexible debugging macros:

Click Run ▶

However, this version will cause a compile error if no arguments are passed for __VA_ARGS__ as below shown:

Click Run ▶

To fix it, use ##__VA_ARGS__ instead, which removes the preceding comma if no arguments follow:

Click Run ▶

In this example, ##__VA_ARGS__ ensures that the comma is safely removed if VA_ARGS is empty.

3.4. Predefined Debugging Macros

You can also use standard predefined macros to show contextual information like the file name, line number, or function name:

  • __FILE__: Expands to the current file name
  • __LINE__: Expands to the current line number
  • __func__: Expands to the name of the current function
Click Run ▶

This is particularly useful for tracing execution or reporting errors during development.

3.5. Previous

Previous: User-defined Macro(1): Basics

This post is licensed under CC BY 4.0 by the author.