C,宏参数,参数替换

时间:2018-03-28 14:52:33

标签: c gcc macros

我有一个编译得很好的旧代码(对于NXP micro也是gcc,不记得是哪个版本)

#define TIME_CONSTANT     250,mSec

if (SysTimerOnTime(tmr, TIME_CONSTANT)) 
{

}

现在我尝试为ESP8266做同样的事情,使用gcc for Xtensa

xtensa-lx106-elf-gcc.exe (GCC) 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我正在使用-std = c99(因为某些内联asm)

投诉是关于在SysTimerOnTime宏中传递2个参数,需要3.所以,如果我使用:

if (SysTimerOnTime(tmr, 250, mSec)) 

会正常工作。

会出现什么问题?

我很肯定LpcXpresso工作得很完美(也就是gcc),但由于工具链不再安装,我现在无法测试。

宏就像这样

#define SysTimerOnTime(t,v,unit)    (t.Enable && (Now()-t.Value) > unit(v))

看起来双重间接成功了。也许LPCXpresso使用较旧的编译器。没关系,这很有效,谢谢Jonathan Leffler

#define TIME_CONSTANT     250,mSec
#define     SysTimerOnTime_(t,v,unit)   (t.Enable && (Now()-t.Value) > unit(v))
#define     SysTimerOnTimeX(x) x
#define     SysTimerOnTime(tmr, con)    SysTimerOnTimeX(SysTimerOnTime_(tmr, con))

1 个答案:

答案 0 :(得分:4)

在评估SysTimerOnTime()的调用时,在任何参数扩展之前收集参数。只有两个参数 - 因此宏调用不正确。您必须引入一个间接级别才能使用TIME_CONSTANT宏。例如:

#define SysTimerOnTimeC(tmr, con) SysTimerOnTimeX(SysTimerOnTime(tmr, con))
#define SysTimerOnTimeX(x) x

然后你可以调用:

if (SysTimerOnTimeC(tmr, TIME_CONSTANT))
{
    …
}

C代表'恒定'; X代表“扩张”。您不直接从代码调用SysTimerOnTimeX()宏;它只是一个帮手宏。

我不禁觉得你会更好:

#define QUARTER_SECOND mSec(250)
#define SysTimerOnTime(t, v)    ((t).Enable && (Now()-(t).Value) > (v))

然后调用:

if (SysTimerOnTime(tmr, QUARTER_SECOND)) 
{
    …
}

我还在扩展中将两个参数括起来。这是传统的,通常是明智的建议(虽然绝对不是答案的主要部分所需要的)。没有括号,如果你曾经调用过,你会得到编译器的抱怨:

if (SysTimerOnTime(*ptr, QUARTER_SECOND))

因为*的优先级低于.。额外的括号应该应用于基础SysTimerOnTime宏。