两次通过C预处理?

ner*_*com 5 c macros gcc c-preprocessor

有没有办法让C预处理器(GCC)运行两次通过,以完全扩展宏?

我正在尝试使用引脚的抽象名称来定义支持微控制器上端口I/O的宏:

#define LED_RED E, (1<<6)

#define SetPin(port, mask)    PORT ## port ## SET = (mask)
#define ClearPin(port, mask)  PORT ## port ## CLR = (mask)
#define ReadPin(port, mask)   (PORT ## port) & (mask)
Run Code Online (Sandbox Code Playgroud)

然后在我的代码中:

SetPin(LED_RED);
ClearPin(LED_RED);
result = ReadPin(LED_RED);
Run Code Online (Sandbox Code Playgroud)

这意味着扩展到:

PORTESET = (1<<6);
PORTECLR = (1<<6);
result = (PORTE) & (1<<6);
Run Code Online (Sandbox Code Playgroud)

这不编译 - 我得到:

错误:宏"SetPin"需要2个参数,但只有1个参数.

虽然这确实编译和工作正常:

SetPin(E, (1<<6));
Run Code Online (Sandbox Code Playgroud)

那么......如何让C编译器完全扩展这些宏呢?

或者,如果不是这样,如何使这种事情发挥作用?

und*_*gor 13

您必须通过另一个宏传递参数.

#define LED_RED E, (1<<6)
#define SetPin2(port, mask)    PORT ## port ## SET = (mask)
#define SetPin(x) SetPin2(x)

SetPin(LED_RED);
Run Code Online (Sandbox Code Playgroud)

这是由于宏替换的顺序:

  1. 首先,确定类似函数的宏的参数.如果参数的数量错误(如在您的代码中),这已经失败.
  2. 然后,参数标记被放入替换列表中.除非他们旁边##或者#,他们获得前宏扩展.
  3. 最后,扫描生成的替换列表以进行进一步的宏替换.

使用额外的宏"介于两者之间",第二步有机会替换LED_RED.