在C语言中如何定义元组

8

我希望能够定义一个元组,它代表其他宏所需的参数。

我认为最好的方法是通过示例来说明我想要的:

#include <avr/io.h>

#define LED_PORT PORTB
#define LED_DDR  DDRB
#define LED_PIN  PB7
#define LED      LED_PORT, LED_DDR, LED_PIN

#define OUTPUT(port, ddr, pin) ddr |= 1 << pin

void main(void) {
    OUTPUT(LED);
}

我希望OUTPUT(LED)可以被扩展为以下内容:
LED_DDR |= 1 << LED_PIN

我遇到的问题与扩展顺序有关,导致出现如下错误:

宏“OUTPUT”需要3个参数,但只提供了1个

这是用于AVR项目的自定义硬件环境的情况,我已经定义了LED和其他组件以及相应的LED_PORT、LED_DDR和LED_PIN。
然后,我想定义更多的宏,可以使用该LED并使用适当的参数来映射到最简洁的方式。
标准C预处理器能实现这个吗?

展示 LET_PINLET_PORTLET_DDROUTPUT 的定义。因此,请编辑您的问题以改进它。 - Basile Starynkevitch
1
我会使用[tag:c-preprocessor]标记这个问题。 - Michas
我们可以假设 PORTBDDRBPB7 是整型常量吗? - Basile Starynkevitch
@Michas 那个标签没有出现。我会再试一次。 - flungo
1
@BasileStarynkevitch PB7是一个整型常量,PORTBDDRB的形式为(*(volatile uint8_t*) (some_address)) - Wintermute
1个回答

6
您可以通过在宏中添加间接层来实现此目的:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)

在重新扫描期间,specOUTPUT_I之前被扩展,因此OUTPUT_I宏将看到三个参数。

我有这个印象,这段代码无法编译通过。OUTPUT_I需要三个参数。 - alk
@alk它有三个参数,因为在重新扫描期间函数宏之前,函数参数被展开(正如我在答案中提到的)。 - Wintermute
没错。我以前也用过类似的技巧:#define FOO (1, 2)#define BAR_I(x, y) ...#define BAR(spec) BAR_I spec;这些都能起作用的原因是一样的。预处理器的规则很神秘,但增加一个间接层确实可以解决您可能遇到的许多问题。值得一试。 - Wintermute
看起来行得通。现在尝试使用我的WRITE函数,它将接受第四个参数以及spec。应该可以做到同样的事情,只需要将第二个参数传递为第四个参数即可。 - flungo
1
我认为它是“间接的”。任何名称都可以,如果你觉得它令人困惑,选择其他名称即可。我认为这种事情没有既定的惯例。 - Wintermute
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接