C语言 带参数的宏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5382271/
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
macro with arguments
提问by Andrei
Let's say I define macro with arguments, then invoke it as follows:
假设我用参数定义宏,然后按如下方式调用它:
#define MIN(x,y) ((x)<(y)?(x):(y))
int x=1,y=2,z;
z=MIN(y,x);
Given that (a) macro works as text substitution, (b) that actual args here are like formal args, only swapped, -- will this specfic z=MIN(y,x) work as expected ? If it will, why ? I mean, how preprocessor manages not to confuse actual and formal args ?
鉴于 (a) 宏用作文本替换,(b) 这里的实际 args 就像正式的 args,只是交换了,-- 这个特定的 z=MIN(y,x) 会按预期工作吗?如果会,为什么?我的意思是,预处理器如何设法不混淆实际和正式的 args ?
This question is about technicalities of C compiler. This is not c++ question.
This question does not recommend anybody to use macros.
This question is not about programming style.
这个问题是关于C 编译器的技术细节。这不是 C++ 问题。
这个问题不建议任何人使用宏。
这个问题与编程风格无关。
采纳答案by zwol
The internal representation of the macro will be something like this, where spaces indicate token boundaries, and #1and #2are magic internal-use-only tokens indicating where parameters are to be substituted:
宏的内部表示将是这样的,其中空格表示标记边界,而#1和#2是神奇的仅供内部使用的标记,表示要替换参数的位置:
MIN( #1 , #2 ) --> ( ( #1 ) < ( #2 ) ? ( #1 ) : ( #2 ) )
-- that is to say, the preprocessor doesn't make use of the names of macro parameters internally (except to implement the rules about redefinitions). So it doesn't matter that the formal parameter names are the same as the actual arguments.
-- 也就是说,预处理器在内部不使用宏参数的名称(除了实现有关重定义的规则)。所以形式参数名称与实际参数名称相同并不重要。
What cancause problems is when the macro body makes use of an identifier that isn'ta formal parameter name, but that identifier also appears in the expansionof a formal parameter. For instance, if you rewrote your MINmacro using the GNU extensions that let you avoid evaluating arguments twice...
什么能引起问题是,当宏体利用一个标识符的是不是一个正式的参数名称,但标识也出现在扩张形式参数。例如,如果您MIN使用 GNU 扩展重写了宏,以避免对参数求值两次......
#define MIN(x, y) ({ \
__typeof__(x) a = (x); \
__typeof__(y) b = (y); \
a < b ? a : b; \
})
and then you tried to use it like this:
然后你尝试像这样使用它:
int minint(int b, int a) { return MIN(b, a); }
the macro expansion would look like this:
宏扩展如下所示:
int minint(int b, int a)
{
return ({
__typeof__(b) a = (b);
__typeof__(a) b = (a);
a < b ? a : b;
});
}
and the function would always return its first argument, whether or not it was smaller. C has no way to avoid this problem in the general case, but a convention that many people use is to alwaysput an underscore at the end of the name of each local variable defined inside a macro, and neverput underscores at the ends of any other identifiers. (Contrast the behavior of Scheme's hygienic macros, which are guaranteed to not have this problem. Common Lisp makes you worry about it yourself, but at least there you have gensymto help out.)
并且该函数将始终返回它的第一个参数,无论它是否更小。C在一般情况下没有办法避免这个问题,但是很多人使用的约定是总是在宏中定义的每个局部变量的名称末尾加上下划线,并且永远不要在任何末尾加上下划线其他标识符。(对比 Scheme 的hygienic macros的行为,它们保证不会有这个问题。Common Lisp 让你自己担心,但至少你必须在那里gensym帮忙。)
回答by Puppy
It will work as expected.
它会按预期工作。
#define MIN(x, y) ((x) < (y) ? (x) : (y))
int x=1,y=2,z;
z = MIN(y, x);
becomes
变成
int x=1,y=2,z;
z = ((y) < (x) ? (y) : (x));
Does the above have any syntactic or semantic errors? No. Therefore, the result will be as expected.
以上是否有任何语法或语义错误?不会。因此,结果将如预期的那样。
回答by Fred Larson
Since you're missing a close ')', I don't think it will work.
由于您缺少一个关闭的 ')',我认为它不会起作用。
Edit:
Now that's fixed, it should work just fine. It won't be confused by xand yany more than it would be if you has a string xwith "x" in it.
编辑:现在已经解决了,它应该可以正常工作。如果您有一个带有“x”的字符串,它不会被混淆,x并且不会被混淆。yx
回答by Alexander Kondratskiy
First off, this isn't about the C compiler, this is about the C Pre-processor. A macro works much like a function, just though text substitution. What variable names you use make no impact on the outcome of the macro substitution. You could have done:
首先,这不是关于 C 编译器,而是关于 C 预处理器。宏的工作方式与函数非常相似,只是文本替换。您使用的变量名称对宏替换的结果没有影响。你可以这样做:
#define MIN(x,y) ((x)<(y)?(x):(y))
int blarg=1,bloort=2,z;
z=MIN(bloort,blarg);
and get the same result.
并得到相同的结果。
回答by Brian
As a side node, the min() macro is a perfect example of what can go wrong when using macros, as an exercise you should see what happens when you run the following code:
作为辅助节点,min() 宏是使用宏时可能出错的完美示例,作为练习,您应该看看运行以下代码时会发生什么:
int x,y,z;
x=1;y=3;
z = min(++x,y);
printf("%d %d %d\n", x,y,z); /* we would expect to get 2 3 2, but we get 3 3 3 . */

