Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

macro with arguments

Tags:

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 ?

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.

like image 954
Andrei Avatar asked Mar 21 '11 18:03

Andrei


People also ask

How do you use macros in arguments?

Function-like macros can take arguments , just like true functions. To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. The parameters must be valid C identifiers, separated by commas and optionally whitespace.

How do I pass an argument to a macro in Excel?

To assign a macro that you pass arguments to a button, shape, image, or any object, you first right-click that object and click Assign Macro and then type the name of the macro and the argument, following the pattern described in the above examples, and then click OK. 'show_msg "I clicked a button!"'

What is the correct way to name a macro with two arguments?

Macros with arguments To create a macro with arguments, put them in parentheses separated by commas after the macro name, e.g.

How many arguments macro can have?

A comma must separate each parameter. For portability, you should not have more than 31 parameters for a macro. The parameter list may end with an ellipsis (…).


2 Answers

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.)

like image 85
zwol Avatar answered Oct 13 '22 15:10

zwol


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.

like image 29
Puppy Avatar answered Oct 13 '22 15:10

Puppy