开发者

macro with arguments

开发者 https://www.devze.com 2023-02-18 00:44 出处:网络
Let\'s say I define macro with arguments, then invoke it as follows: #define MIN(x,y) ((x)<(y)?(x):(y))

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=MI开发者_如何学JAVAN(y,x) work as expected ? If it will, why ? I mean, how preprocessor manages not to confuse actual and formal 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.


The internal representation of the macro will be something like this, where spaces indicate token boundaries, and #1 and #2 are magic internal-use-only tokens indicating where parameters are to be substituted:

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 can cause problems is when the macro body makes use of an identifier that isn't a formal parameter name, but that identifier also appears in the expansion of a formal parameter. For instance, if you rewrote your MIN macro using the GNU extensions that let you avoid evaluating arguments twice...

#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 always put an underscore at the end of the name of each local variable defined inside a macro, and never put 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 gensym to help out.)


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.


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 x and y any more than it would be if you has a string x with "x" in it.


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:

#define MIN(x,y) ((x)<(y)?(x):(y))
int blarg=1,bloort=2,z;
z=MIN(bloort,blarg);

and get the same result.


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:

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 . */
0

精彩评论

暂无评论...
验证码 换一张
取 消