【问题标题】:Comparing C macros比较 C 宏
【发布时间】:2017-03-22 16:43:21
【问题描述】:

我有寻址宏(它在微控制器上,所以访问物理地址是可以的)分解成这个(经过一长串的条件定义、属性等):

#define ADDR_A (*18)
#define ADDR_B (*30)
#define ADDR_C (*18)

我想比较它们以便优化编译:

#if ADDR_A==ADDR_C
    return 1;
#else
    return 0;
#endif

但我得到“错误:运算符'*'没有左操作数”,这是有道理的。是否可以比较宏的定义。我有一种预感,我可以以某种方式将它们转换为字符串进行比较,但我还没有找到一种方法(比如用 # 表示宏参数)。

不,我不打算在运行时执行此操作,因为我正在计算周期。

【问题讨论】:

  • 这不是有效的 C。编译器应该如何知道它是一个地址以及对象的类型?您的其余问题尚不清楚。你想比较什么,为什么?它闻起来像 XY 问题。
  • 我完全同意@Olaf。此外,如果表达式只有文字常量(就像您要比较两个内存映射寄存器的地址一样),我使用的所有 C 编译器都会优化普通的 if 语句;而且,由于您使用的是微控制器,因此您绝对应该启用优化。换句话说,不需要依赖预处理器来优化相关代码;任何半体面的 C 编译器都可以并且将为您完成(如果您使用普通的 C if 语句)。

标签: c macros preprocessor


【解决方案1】:

您无法比较 #if 中的字符串,因为:

  • 您只能将#if 与常量表达式一起使用
  • 字符串只能使用循环或函数进行比较
  • 循环不是常量表达式
  • 和:

    常量表达式不应包含赋值、递增、递减、函数调用、 或逗号运算符,除非它们包含在不属于 评估。 (C11, 6.6P3)

我能想到的最好的办法是将地址和解引用分成两个不同的宏,例如:

#define ADDR_A (18)
#define ADDR_B (30)
#define ADDR_C (18)
#define GET_A (*ADDR_A)
#define GET_B (*ADDR_B)
#define GET_C (*ADDR_C)

#if ADDR_A == ADDR_B
return 1
#else
return 0
#endif

请注意,几乎所有有价值的编译器都会忽略“在运行时”检查常量的相等性;在this example 中,编译器只生成return 1 的等价物,因为它在编译时知道条件将评估为假;计算周期在这里是一个红鲱鱼,因为这些比较将被忽略。

另外,对于它的价值,我不确定你是如何使用这些宏的(我无法在脑海中构建一个它们在语法上有效的示例),但我感觉你的代码会是如果您刚刚使宏包含地址并且您在代码中内联取消引用这些地址,则更容易理解。如果我阅读您的代码,我会更喜欢:

#define ADDR_A (18)
#define ADDR_B (30)
#define ADDR_C (18)

if (ADDR_A == ADDR_B)
    return 1
return 0

【讨论】:

    【解决方案2】:

    宏中只放地址,类型信息分开放怎么样?

    #define ADDR_A (18)
    #define ADDR_B (30)
    #define ADDR_C (18)
    
    unsigned uint16_t *A = (uint16_t*)ADDR_A;
    unsigned uint16_t *B = (uint16_t*)ADDR_B;
    unsigned uint16_t *C = (uint16_t*)ADDR_C;
    

    然后你就可以使用你的测试了。

    或者,跳过预处理器,直接在 C 中完成:

    unsigned uint16_t *const A = (uint16_t*)18;
    unsigned uint16_t *const B = (uint16_t*)30;
    unsigned uint16_t *const C = (uint16_t*)18;
    
    int f()
    {
        if (A == C)
            return 1;
        else
            return 0;
    }
    

    除非你有一个非常低质量的编译器,你可以期望它把A==C识别为一个常量表达式并相应地简化代码。

    【讨论】:

      猜你喜欢
      • 2011-07-31
      • 1970-01-01
      • 2020-07-01
      • 2014-04-04
      • 2015-07-29
      • 1970-01-01
      • 2019-03-13
      • 2015-11-28
      • 1970-01-01
      相关资源
      最近更新 更多