C中类似函数的宏定义

我想定义像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 。 它可以用(2*33)代替foo(33) (2*33)

你可以如下

 #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”),而不是评估任何值。

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

考虑:

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

x在编译时是未知的。

 int a = foo(31); 

扩展到

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

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

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

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

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

问题与理论无关:假设您出于某种原因希望根据传递给它的参数值有一个不同扩展的宏,并且此参数是一个常量,宏预处理器已知,则没有为什么它无法工作…对于通用宏处理器…但是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这么容易……