C语言 C 中类似函数的宏定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3215171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:50:29  来源:igfitidea点击:

Function-like macro definition in C

cgccc-preprocessor

提问by richard

I'd like to define a function like MACRO . i.e.

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

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

that is,

那是,

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

but my GCC complains about:

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

int a = foo(31);

I think C preprocessor should be handle this correctly. since at compile time, it knows x=33. it could replace foo(33)with (2*33)

我认为 C 预处理器应该正确处理这个问题。因为在编译时,它知道x=33. 它可以替换foo(33)(2*33)

回答by Johannes Schaub - litb

You can as follows

你可以如下

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

But that evaluates xmultiple times. You can instead create a static function, which is cleaner

但这会评估x多次。您可以改为创建一个更清晰的静态函数

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

Then you are also able to pass things to foothat have side effects, and have the side effect happen only one time.

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

What you have written is using the #if, #elseand #endifpreprocessor directives, but you need to use language constructs if you pass variables to the macro and want to evaluate their values. Using if, and elsestatements as in the actual language constructs don't work either, because control flow statements don't evaluate to values. In other words, an if statement is steering control flow only ("if A, then execute B, else execute C"), not evaluating to any values.

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

回答by Vanni Totaro

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

回答by richard

Consider:

考虑:

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

x is not known at compile time.

x 在编译时未知。

回答by Thom Smith

int a = foo(31);

Expands out to

扩展到

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

That's how C macros work, via simple, dumb substitution. If you expect gcc to do anything more complex or intelligent with them, then your expectation is erroneous.

这就是 C 宏的工作方式,通过简单的、愚蠢的替换。如果您期望 gcc 对它们做任何更复杂或更智能的事情,那么您的期望是错误的。

Given that, it's easy to see why your code won't work. An alternative that would suffice for this example would be:

鉴于此,很容易看出为什么您的代码不起作用。足以满足此示例的替代方案是:

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

On the other hand, I would question whether macros are really the appropriate tool for such a thing to begin with. Just put it in the function and the compiler will inline the code if it thinks it will speed it up.

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

回答by ShinTakezou

The problem is not about the theory: provided that you, for some reason, want to have a macro that expands differently according to the value of a parameter passed to it, and this parameter is a constant, known to the macro preprocessor, there's no reason why it couldn't work... for a generic macro processor... But cpp unluckly does not allow the presence of other macro processor "commands" into a macro definition...

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

So your

所以你的

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

does not expand to

不会扩展到

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

where X is the known parameter (so change X to e.g. 31), which requires another pass by the preprocessor.

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

Moreover newlines are ignored, while they are important for such an use; otherwise, the following could be considered as a trick (that need another preprocessing pass however)

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

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

that with foo(20,#)produces

foo(20,#)产生

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

which would work, if it would be

哪个会起作用,如果是的话

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

... but it is not (and as said, the output of the preprocessor must be feeded to the preprocessor again...)

...但事实并非如此(如前所述,预处理器的输出必须再次提供给预处理器...)

So my answer is that if you need these things, you can't use the C preprocessor; you should use a uncommon (not standard?) C preprocessor, or just another macro processor, and if you need the sort of things that "cpp" has to "integrate" itself with C, then you can't use a generic one (like M4) so easily...

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