两遍 C 预处理?
Two pass C preprocessing?
有没有办法让 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)
然后在我的代码中:
SetPin(LED_RED);
ClearPin(LED_RED);
result = ReadPin(LED_RED);
这意味着扩展到:
PORTESET = (1<<6);
PORTECLR = (1<<6);
result = (PORTE) & (1<<6);
这无法编译 - 我得到:
error: macro "SetPin" requires 2 arguments, but only 1 given.
虽然这确实可以编译并且工作正常:
SetPin(E, (1<<6));
那么...如何让 C 编译器完全展开这些宏?
或者,如果不是那样,如何使这种事情起作用?
您必须通过附加宏传递参数。
#define LED_RED E, (1<<6)
#define SetPin2(port, mask) PORT ## port ## SET = (mask)
#define SetPin(x) SetPin2(x)
SetPin(LED_RED);
这是因为宏替换的顺序:
- 首先,确定类函数宏的参数。这已经
如果参数数量错误(如您的代码中所示),则会失败。
- 然后,参数标记被放入替换列表。除非它们在
##
或 #
旁边,否则它们会被宏扩展
之前。
- 最后,扫描生成的替换列表以进行进一步的宏替换。
有了额外的宏 "in between",第 2 步就有机会替换 LED_RED
。
有没有办法让 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)
然后在我的代码中:
SetPin(LED_RED);
ClearPin(LED_RED);
result = ReadPin(LED_RED);
这意味着扩展到:
PORTESET = (1<<6);
PORTECLR = (1<<6);
result = (PORTE) & (1<<6);
这无法编译 - 我得到:
error: macro "SetPin" requires 2 arguments, but only 1 given.
虽然这确实可以编译并且工作正常:
SetPin(E, (1<<6));
那么...如何让 C 编译器完全展开这些宏?
或者,如果不是那样,如何使这种事情起作用?
您必须通过附加宏传递参数。
#define LED_RED E, (1<<6)
#define SetPin2(port, mask) PORT ## port ## SET = (mask)
#define SetPin(x) SetPin2(x)
SetPin(LED_RED);
这是因为宏替换的顺序:
- 首先,确定类函数宏的参数。这已经 如果参数数量错误(如您的代码中所示),则会失败。
- 然后,参数标记被放入替换列表。除非它们在
##
或#
旁边,否则它们会被宏扩展 之前。 - 最后,扫描生成的替换列表以进行进一步的宏替换。
有了额外的宏 "in between",第 2 步就有机会替换 LED_RED
。