【问题标题】:Is there a way to write a macro pattern that somehow avoids preprocessor prescan expansion?有没有办法编写一个以某种方式避免预处理器预扫描扩展的宏模式?
【发布时间】:2019-10-01 16:52:20
【问题描述】:

我想知道是否存在编写预处理器宏的模式可以有效地“跳过”预扫描宏扩展。

#include <stdio.h>

#define SHIFT(label) label##_SHIFT
#define WIDTH(label) label##_WIDTH

#define MSB(label) label##_SHIFT + label##_WIDTH

#define A_SHIFT 0
#define A_WIDTH 4

#if 1
#define B_SHIFT 4
#else
/* Something like this would be preferred over, say
 * #define B_SHIFT A_SHIFT + A_WIDTH
 */
#define B_SHIFT MSB(A)  
#endif
#define B_WIDTH 4

int main(int argv, char ** argc) {
    (void)argv;
    (void)argc;

    (void)printf("A: Width %d\n", WIDTH(A));
    (void)printf("A: Shift %d\n", SHIFT(A));
    (void)printf("A: MSB   %d\n", MSB(A));

    (void)printf("B: Width %d\n", WIDTH(B));
    (void)printf("B: Shift %d\n", SHIFT(B));
    (void)printf("B: MSB   %d\n", MSB(B));
    return 0;
}

在上面的人为示例中,如果使用B_SHIFT 宏的第二种形式,预处理器第一次扫描中的宏定义想要扩展A,(当然)它不能。

是否可以使用一些预处理器技巧,以便它可以有效地执行第二种形式?

【问题讨论】:

    标签: macros c-preprocessor


    【解决方案1】:

    在上面的人为示例中,如果使用 B_SHIFT 宏的第二种形式,则预处理器第一次扫描中的宏定义想要扩展 A,(当然)它不能。

    这里的问题是您已经安排将MSB(B) 替换为自身尝试替换MSB(A)。 C 预处理器不允许递归替换相同的宏,即使在这种递归完全安全的情况下也是如此。在宏替换中,被替换的宏的名称实际上是未定义的。您看到引用 A 的错误消息的事实是 MSB(A) 未经更改地传递的结果,结果 MSBA 在预处理后都显示为标记。由于两者都没有被声明,编译器抱怨使用了未声明的函数 (MSB) 和变量 (A)。

    一个简单(但显然不理想)的解决方法是使用两个相同的宏定义:

    #define SHIFT(label) label##_SHIFT
    #define WIDTH(label) label##_WIDTH
    
    #define MSB(label) label##_SHIFT + label##_WIDTH
    #define MSB_(label) label##_SHIFT + label##_WIDTH
    
    #define A_SHIFT 0
    #define A_WIDTH 4
    #define B_SHIFT MSB_(A)  
    #define B_WIDTH 4
    

    这将允许B_SHIFT 的扩展在MSB(B) 的扩展中进行扩展。

    如果您想了解不同的解决方案可能是什么样子,可以查看Boost Preprocessor library

    【讨论】:

    • 因此,如果我想将宏扩展为 C_SHIFT/WIDTHD_SHIFT/WIDTH,同时菊花链 MSB() 宏,我唯一的办法是添加更多带有增加下划线的 MSB 定义(或其他独特的标识符)?
    • @jamie:菊花链的长度很重要。这就是 boost-pp 链接中策略的重点。
    猜你喜欢
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 2018-05-06
    • 2018-01-04
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    相关资源
    最近更新 更多