Understanding Macro Expansion Rules in C Language



πŸ‘† Click the blue text "Linux Armory" at the top, and select "Add to Favorites" in the upper right corner

Don’t miss out on great articles, see valuable content first

Understanding Macro Expansion Rules in C Language

πŸ‘† FollowLinux Armory, to receive hardcore Linux learning materials and code

unset1. Macro Expansion Rulesunsetunset

In the C language preprocessor, if a macro parameter itself is a macro, the timing of its expansion follows certain rules. Specifically, the timing of the macro parameter’s expansion depends on its position and usage in the macro definition. Here are the detailed rules and explanations:

Timing of Macro Parameter Expansion

When a macro is called, the preprocessor processes the macro parameters according to the following steps:

Parameter Replacement

  • During the macro call, the preprocessor replaces the macro parameters with actual arguments.
  • If the macro parameter itself is a macro, the preprocessor first expands this macro parameter before performing the replacement.

Macro Expansion in Replacement List

  • In the replacement list, the preprocessor processes each symbol one by one. If the symbol is a macro, the preprocessor further expands this macro.
  • However, if the symbol is a macro parameter and this macro parameter is used as a parameter for the <span>#</span> or <span>##</span> operators in the replacement list, this macro parameter will not be expanded.

Specific Rules

  • Parameter Expansion Takes Precedence Over Replacement List Expansion: Macro parameters are expanded before being replaced in the replacement list.
  • Macro Expansion in Replacement List: Symbols in the replacement list (including expanded parameters) will be further expanded unless they are used as parameters for the <span>#</span> or <span>##</span> operators.

Examples

Example 1: Parameter Expansion Takes Precedence

Assume we have the following macro definition:

#define A 123
#define PRINT(x) printf("%d\n", x)

Calling the macro:

PRINT(A);

Expansion process:

  1. Parameter Replacement:<span>A</span> is a macro, the preprocessor first expands <span>A</span>, resulting in <span>123</span>.

  2. Replacement List Expansion: Replace <span>123</span> in the <span>PRINT</span> replacement list, resulting in:

    printf("%d\n", 123);
    

Final output:

123

Example 2: Parameter Not Expanded (<span>#</span> Operator)

Assume we have the following macro definition:

#define A 123
#define STRINGIFY(x) #x

Calling the macro:

printf("%s\n", STRINGIFY(A));

Expansion process:

  1. Parameter Replacement:<span>A</span> is a macro, but since <span>STRINGIFY</span> uses the <span>#</span> operator in its replacement list, <span>A</span> will not be expanded.

  2. Replacement List Expansion: Replace <span>A</span> in the <span>STRINGIFY</span> replacement list, resulting in:

    printf("%s\n", "A");
    

Final output:

A

Example 3: Parameter Not Expanded (<span>##</span> Operator)

Assume we have the following macro definition:

#define A 123
#define CONCAT(x, y) x##y

Calling the macro:

CONCAT(A, B);

Expansion process:

  1. Parameter Replacement:<span>A</span> is a macro, but since <span>CONCAT</span> uses the <span>##</span> operator in its replacement list, <span>A</span> will not be expanded.

  2. Replacement List Expansion: Replace <span>A</span> and <span>B</span> in the <span>CONCAT</span> replacement list, resulting in:

    AB
    

Final result:<span>AB</span> is a symbol, not <span>123B</span>.

4. Rules

  • Parameter Expansion Takes Precedence: Macro parameters are expanded before being replaced in the replacement list.
  • Macro Expansion in Replacement List: Symbols in the replacement list will be further expanded unless they are used as parameters for the <span>#</span> or <span>##</span> operators.
  • Special Cases: If a macro parameter is used as a parameter for the <span>#</span> or <span>##</span> operators in the replacement list, this macro parameter will not be expanded.

unsetunset2. Handling Non-Expanded Macro Parametersunsetunset

#define STRINGIFY(x)    STRINGIFY_HELPER(x)
#define STRINGIFY_HELPER(x)     #x

#define STRINGCAT(x, y)  STRINGCAT_HELPER(x, y)
#define STRINGCAT_HELPER(x, y)  x##y

These rules ensure that the macro expansion process is predictable while also providing a flexible way to control macro behavior.

This code defines two macros <span>STRINGIFY</span> and <span>STRINGIFY_HELPER</span>, as well as <span>STRINGCAT</span> and <span>STRINGCAT_HELPER</span>. The reason for needing two macros to achieve functionality instead of using a single macro directly is due to the working mechanism of the C preprocessor.

Explanation of Reasons

  1. Preprocessor Expansion Rules In the C preprocessor, macro parameters are not immediately replaced with actual values during the first expansion; they retain their original form. Only through indirect expansion (i.e., via another macro call) can the actual values of the parameters be correctly resolved.

  2. Specific Scenario Analysis

  • For <span>STRINGIFY(x)</span>, if defined directly as <span>#x</span>, it cannot correctly handle macros with parameters or complex expressions. By using <span>STRINGIFY_HELPER(x)</span> for indirect calls, it ensures that parameters are correctly expanded before being stringified.
  • Similarly, for <span>STRINGCAT(x, y)</span>, if defined directly as <span>x##y</span>, it cannot correctly concatenate macros with parameters or complex expressions. By using <span>STRINGCAT_HELPER(x, y)</span> for indirect calls, it ensures that parameters are correctly expanded before concatenation.
  • Example Comparison Assume we have the following code:

    #define FOO 123
    #define STRINGIFY(x)    #x
    #define STRINGCAT(x, y) x##y
    
    const char* str = STRINGIFY(FOO); // Result is "FOO" instead of "123"
    int value = STRINGCAT(FOO, 456);  // Result is FOO456 instead of 123456
    

    If using indirect macros:

    #define STRINGIFY(x)    STRINGIFY_HELPER(x)
    #define STRINGIFY_HELPER(x)     #x
    #define STRINGCAT(x, y)  STRINGCAT_HELPER(x, y)
    #define STRINGCAT_HELPER(x, y)  x##y
    
    const char* str = STRINGIFY(FOO); // Result is "123"
    int value = STRINGCAT(FOO, 456);  // Result is 123456
    
  • Through indirect macro calls, parameters are correctly expanded, achieving the expected functionality.

    unsetunsetConclusionunsetunset

    The reason for defining two macros is to utilize the two-step expansion mechanism of the C preprocessor, ensuring that macro parameters can be correctly resolved and processed. If only one macro were used, it would not be able to correctly handle complex macro parameters or expressions.

    ↓↓ Recommended Articles ↓↓

    πŸ‘‰ Detailed Method for Creating Library Files in Linux

    πŸ‘‰ Summary of Most Common Command Usages in Linux (Selected)

    πŸ‘‰ Step-by-Step Guide to Writing Linux Thread Pools

    πŸ‘‰ Summary of Common Methods in Linux Shell Programming

    πŸ‘‰ Essence of C++ Basic Knowledge

    ↓↓ Recommended Collections ↓↓

    πŸ‘‰ Collection of C Language Introductory Tutorials

    πŸ‘‰ Collection of Common Software Tools

    πŸ‘‰ Collection of Linux Knowledge

    πŸ‘‰ Collection of Detailed Linux Libraries

    πŸ‘‰ Linux Application Programming Collection

    Understanding Macro Expansion Rules in C Language

    For learning and communication, pleaseadd Assistant WeChat to join a high-quality learning group

    πŸ‘‡ Learn from others’ strengths to make up for your own shortcomings πŸ‘‡

    Please click→【Technical Learning Group】

    ❝

    FollowLinux Armory, reply in the chat interface withγ€Œ1024」 to get all Linux materials and code.

    ❞

    Technical work requires step-by-step accumulation, building up to significant resultsγ€ŒDo not regret wasting time, do not feel ashamed of being mediocre」

    Understanding Macro Expansion Rules in C Language

    Make a little progress every day, support the author, remember to like and share! Add the assistant’s WeChat to receive numerous classic open-source project source codes, read anytime, anywhere, there’s always one that can help you!

    Support the author, please extend your little hand to wealth

    Share, collectπŸ‘‡πŸ‘‡πŸ‘‡πŸ‘‡πŸ‘‡Like, see

    Support quality content with action!

    Leave a Comment