比较C宏

时间:2017-03-22 16:43:21

标签: c macros preprocessor

我已经解决了宏(它在微控制器上,因此访问物理地址是正常的),可以分解为(在一长串条件定义,属性等之后):

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

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

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

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

不,我不打算在运行时这样做,因为我在计算周期。

2 个答案:

答案 0 :(得分: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,因为它在编译时知道条件将评估为false;计数周期在这里是一个红色的鲱鱼,因为这些比较将被省略。

另外,对于它的价值,我不确定你是如何使用这些宏的(我不能在我的头脑中构建一个它们在语法上有效的例子) ,但我觉得如果您的宏只包含地址并且您在代码中内联取消引用这些地址,您的代码将更容易理解。如果我正在阅读您的代码,我更愿意:

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

if (ADDR_A == ADDR_B)
    return 1
return 0

答案 1 :(得分:1)

如何仅将地址放在宏中,并单独输入类型信息?

#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识别为常量表达式并相应地简化代码。