Macro with arguments

Let's say I define a macro with arguments, and then call it like this:

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

Given that (a) the macro works like text substitution, (b) the actual arguments here are similar to formal args, only replaced - will this specfic z = MIN (y, x) work as expected? If so, why? I mean, how does the preprocessor manage to not confuse real and formal arguments?

This question concerns the technical features of the C compiler. This is not a C ++ question.
This question does not recommend anyone to use macros.
This question is not about programming style.

+6
c
source share
5 answers

The macro's internal representation will be like this, where spaces indicate the boundaries of the token, and #1 and #2 are magic tokens of internal use, indicating where the parameters should be replaced:

 MIN( #1 , #2 ) --> ( ( #1 ) < ( #2 ) ? ( #1 ) : ( #2 ) ) 

- that is, the preprocessor does not use the internal parameters of the macro (in addition to implement override rules). Therefore, it does not matter that the formal parameter names match the actual arguments.

Which can cause problems when the macro body uses an identifier that is not a formal parameter name, but that identifier also appears when the formal parameter is expanded. For example, if you rewrote your MIN macro using the GNU extensions, which allow you to 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 extension will 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 will always return its first argument, regardless of whether it was smaller. C is not able to avoid this problem in the general case, but the convention that many people use is to always underline at the end of the name of each local variable defined inside the macro, and never put underscores at the ends of any other identifiers. (Contrast the behavior of hygiene macro schemes that are not guaranteed to have this problem. Generic Lisp makes you worry about it yourself, but at least you have gensym to help.)

+9
source share

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

Do the above have syntax or semantic errors? Not. Therefore, the result will be as expected.

+4
source share

Since you are missing the closure ')', I don’t think this will work.

Edit: Now that this is fixed, it should work fine. It will not be confused with x and y more than if you had a string x with "x" in it.

+2
source share

Firstly, this is not about the C compiler, but about the preliminary processor. A macro works just like a function, just replacing the text. What variable names you use do not affect the macro substitution result. You could do:

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

and get the same result.

0
source share

As a side to the node, the min () macro is a great example of what can get corrupted 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
source share

All Articles