【问题标题】:Array of macros in c -- is it possiblec中的宏数组-是否可能
【发布时间】:2016-04-08 06:36:43
【问题描述】:

我想知道是否可以创建类似宏数组的东西。 我已经实现了以下有效的代码:

struct led_cmds_
{ 
    ioport_pin_t *commands[LED_COUNT] ; 
};
struct led_cmds_ the_led_cmd_ ; 

void populate() {
    the_led_cmd_.commands[0] = SPECIFICPIN(0);
}

主要是:

int main(void) 
{
    //.....  
    populate();
    LED_On(the_led_cmd_.commands[0]); 
}

SPECIFICPIN(x) 是宏定义为:

#define SPECIFICPIN(X) (LED##X##_PIN) 

我所希望的是一种方法来做这样的事情:

#define ioport_pin_t* ARR_LED[LED_COUNT] \
for (int j = 0; j < LED_COUNT; j++) ARR_LED[j] = SPECIFICPIN(j);

然后只需要在我想使用特定引脚时调用以下内容

LED_On(ARR_LED[some_number])

当我尝试这样做时,我得到一个 ARR_LED undeclared (first use in this function) 错误。

当我尝试调用 SPECIFICPIN(x) 时,例如,其中 x 是 for 循环中的一个 int 迭代器,我收到一条错误消息,例如“LEDx_PIN”未声明...

【问题讨论】:

  • 不知道您是否使用 gcc 工具链,但无论如何您都需要将 C99 用于 avr-gcc(以及它的支持库)——通常与 -Os 结合使用。为什么不坚持使用内联函数?
  • 编译器对宏一无所知,因为在调用编译器之前它们已被 预处理器 替换。因此宏数组是不可能的
  • 使用硬件寄存器时,为什么需要一个指针数组?那是可疑的代码。
  • 此外,不存在具有可变 I/O 端口数量的硬件。任何集成电路都必须有固定数量的引脚,您不能即时添加和移除它们。只需声明一个对应于最坏情况的数组,然后根据需要使用尽可能多的数组项。
  • 你是想给我做噩梦吗?

标签: c c-preprocessor atmel


【解决方案1】:

您需要处理您的术语。 宏数组是不可能的。宏不是数据类型,而是在您的程序实际编译之前纯粹的文本替换

我猜“使用宏填充数组”是您想要做的。但是不可能在编译时循环中做到这一点 - 您似乎想要通过您的 ioport_pin_t 宏尝试来实现。宏无法扩展到比您最初提供的更多的文本元素实例。没有像在编译时循环通过宏扩展和重复扩展宏这样的功能。

您的for 循环在运行时循环,而宏在编译时展开。一旦你让自己知道预处理器做了什么,编译器做了什么,以及完成的程序在运行时做了什么,你就会发现那是行不通的。

类似

#define P(X) {(LED##X##_PIN)}

ioport_pin_t *commands[LED_COUNT] = {
  P(0), P(1), P(2),......}

#undefine P

可能是最接近您想要的东西。请注意,预处理器的主要用途不是为了节省您的打字工作量 - 您最好在编辑器中使用复制和粘贴,实现相同的效果并获得更清晰的代码。

【讨论】:

  • 复制粘贴违反DRY规则,是very easy to make mistake
  • 如果复制和粘贴澄清您的程序正在做什么(反复初始化数组成员)它不违反任何规则恕我直言。至少您可以立即看到正在发生的事情,您没有使用(最好)短#defines 污染预处理器名称空间。并且:一般在C语言中很容易出错.....
  • 感谢您的帮助。我最终制作了一堆这样的预处理器指令:#if LED_COUNT == n 添加到位置 n -1 的数组,取消定义 LED_COUNT,然后再次将其定义为 n-1,然后调用 #elif LED_COUNT == n-1 并执行降至 0
【解决方案2】:

一个数组作为 tofro 的答案是要走的路。但是,如果无法简单地用数组解决,那么还有另一种方法可以使用 switch

#define SPECIFICPIN(X) (LED##X##_PIN)

void setpin(int pin, int value)
{
    switch (pin)
    {
    case 1:
        SPECIFICPIN(1) = value;
        doSomething(); // if needed
        break;
    case x: ...
    default: ...
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-14
    • 2011-07-15
    • 2022-12-19
    • 2020-06-27
    • 1970-01-01
    • 2015-10-16
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多