C语言 macro会产生意想不到的行为



我想让我的头文件很容易改变与宏。我正在调试我的代码,似乎这些宏没有做他们应该做的事情。有人能告诉我怎样才能达到以下效果吗?LED_ID_AMS等。

#define LED_NUMBER                  (2)
#define LED_ID_X                    (0)
#define LED_ID_Y                    (1)
#define LED_PIN_X                   (0)
#define LED_PIN_Y                   (3)
#define LED_PORT_X                  (PORTE)
#define LED_PORT_Y                  (PORTG)
#define LED_DD_X                    (DDRE)
#define LED_DD_Y                    (DDRG)
#define LED_PORT(LED_ID_X)          (LED_PORT_X)
#define LED_PORT(LED_ID_Y)          (LED_PORT_Y)
#define LED_PIN(LED_ID_X)           (LED_PIN_X)
#define LED_PIN(LED_ID_Y)           (LED_PIN_Y)
#define LED_DD(LED_ID_X)            (LED_DD_X)
#define LED_DD(LED_ID_Y)            (LED_DD_Y)

我想要实现什么?

我试着这样做,这样我就可以像这样循环通过端口init:

for(i=0;i<LED_NUMBER;i++){
    /* set data direction to output*/
    LED_DD(i)|=((0x01)<<LED_PIN(i));
    /* turn on led */
    LED_PORT(i)|=((0x01)<<LED_PIN(i));
}

您以后会后悔使用了太多宏。实际上,你已经后悔了,因为它们不能工作,而且作为宏,它们很难调试。

还有几点:

  • 您的LED_PIN(i)表达式总是扩展到0
  • 你的LED_PORT(i)表达式总是扩展到PORTE,无论可能是

例如LED_PIN(LED_ID_X)展开为LED_PIN_X。注意,根本没有使用宏参数LED_ID_X。相反,LED_PIN_X只是展开为0

这应该会向您发出警告,例如LED_PORT(SOME_ARG)有几个定义。在LED_PORT(LED_ID_X)中,LED_ID_X只是一个虚拟参数,与常量LED_ID_X完全没有关系。

你可以通过使用常量数组使你的代码具有同样的可读性,也许就像你在这里尝试做的那样,从宏中使用。

除非有大量的 LED_ID_<foo>,否则这充其量只是一个小的简化。不要那样做。如果有很多代码以相同的方式绕过它们,那么定义一个宏来迭代每个操作可能是有意义的,例如:

#define FROB_LEDS \
     action(LED_ID_X); \
     action(LED_ID_Y); \
     action(LED_ID_Z);

并将action(X)本地定义为宏,以对LED X, FROB进行操作,并再次取消定义action。很丑,真的。

您必须添加至少一个:

    数组
  • 内联函数
  • 更复杂的宏

在我看来,还需要对硬件地址进行解引用。

例如,您可以使用宏定义:

#define LED_PORT(i) *(uint16_t *)( 
    (i) == LED_ID_X ? LED_PORT_X : 
    (i) == LED_ID_Y ? LED_PORT_Y : 
    etc)

地点:

#define LED_ID_X     (0)
#define LED_ID_Y     (1)
#define LED_PORT_X   (PORTE)
#define LED_PORT_Y   (PORTG)
#define PORTE        (0x11112222U) // example only
#define PORTG        (0x33334444U) // example only

这里uint16_t只是一个猜测:我假设16位端口在32位地址空间。

或者,使用数组和C99的指定初始化式:

const uint32_t LED_PORT[] = {
    [LED_ID_X] = LED_PORT_X,
    [LED_ID_Y] = LED_PORT_Y
};
#define LED_PORT(i) (*(uint16_t *)LED_PORT[i])

当然,如果没有C99,你可以直接使用:

const uint32_t LED_PORT[] = {LED_PORT_X, LED_PORT_Y};

其中假设 LED_ID_X0,等等

相关内容

  • 没有找到相关文章

最新更新