C中类似函数的宏定义

时间:2010-07-09 17:39:27

标签: c gcc c-preprocessor

我想定义一个像MACRO这样的函数。即。

#define foo(x)\
#if x>32\
 x\
#else\
 (2*x)\
#endif

if x>32, then foo(x) present x
else, foo(x) present (2*x)

但我的海湾合作委员会抱怨:

int a = foo(31);

我认为C预处理器应该正确处理。因为在编译时,它知道x=33。它可以用foo(33)

替换(2*33)

5 个答案:

答案 0 :(得分:12)

您可以按照以下方式

#define foo(x) ((x) > 32 ? (x) : (2 * (x)))

但是多次评估x。您可以改为创建一个更干净的静态函数

static int foo(int x) {
  if(x > 32) 
    return x;
  return 2 * x;
}

然后你也可以将事物传递给有副作用的foo,并且副作用只发生一次。

您所编写的内容是使用#if#else#endif预处理程序指令,但如果将变量传递给宏并想要评估其值,则需要使用语言结构。在实际语言结构中使用ifelse语句也不起作用,因为控制流语句不会计算为值。换句话说,if语句只是转向控制流(“如果A,则执行B,否则执行C”),而不是评估任何值。

答案 1 :(得分:7)

#define \
    foo(x) \
    ({ \
        int xx = (x); \
        int result = (xx > 32) ? xx : (2*xx); \
        result; \
    })

答案 2 :(得分:2)

考虑一下:

int x = rand()
int y = foo( x );

在编译时不知道。

答案 3 :(得分:2)

int a = foo(31);

扩展到

int a = if 31>32
31
else
(2*31)
endif;

这就是C宏的工作方式,通过简单的,愚蠢的替代。如果你希望gcc能够做更复杂或更聪明的事情,那么你的期望就是错误的。

鉴于此,很容易理解为什么你的代码不起作用。一个足以满足这个例子的替代方案是:

#define foo(x) (x > 32 ? x : 2*x)

另一方面,我会质疑宏是否真的是开始这样的事情的合适工具。只需将它放在函数中,如果编译器认为它会加速它,编译器就会内联代码。

答案 4 :(得分:1)

问题与理论无关:假设您出于某种原因希望根据传递给它的参数值有一个不同扩展的宏,并且此参数是一个常量,宏预处理器已知,没有理由为什么它无法工作...对于通用宏处理器...但是cpp不幸地不允许其他宏处理器“命令”存在于宏定义中......

所以你的

#define foo(x) \
#if x>32 \
  x      \
#else    \
  2*x    \
#endif

不会扩展到

#if X>32
  X
#else
  2*X
#endif

其中X是已知参数(因此将X更改为例如31),这需要预处理器再次传递。

此外,新行被忽略,而它们对于这种用途很重要;否则,以下可以被视为一个技巧(但需要另一个预处理过程)

#define foo(x,y) \
y if x>32 \
  x  \
y else \ 
  2*x \
y endif

foo(20,#)生成

# if 20>32 20 # else 2*20 # endif
如果是

会起作用

# if 20>32
  20
# else
  2*20
# endif

...但它不是(如上所述,预处理器的输出必须再次送到预处理器......)

所以我的答案是,如果你需要这些东西,就不能使用C预处理器;你应该使用一个不常见的(不是标准?)C预处理器,或只是另一个宏处理器,如果你需要“cpp”必须与C“集成”自己的东西,那么你不能使用通用的(像M4这么容易......