问题
This question already has an answer here:
- C macros and use of arguments in parentheses 2 answers
I tried to play with the definition of the macro SQR
in the following code:
#define SQR(x) (x*x)
int main()
{
int a, b=3;
a = SQR(b+5); // Ideally should be replaced with (3+5*5+3), though not sure.
printf(\"%d\\n\",a);
return 0;
}
It prints 23
. If I change the macro definition to SQR(x) ((x)*(x))
then the output is as expected, 64
. I know that a call to a macro in C replaces the call with the definition of the macro, but I still can’t understand, how it calculated 23
.
回答1:
Pre-processor macros perform text-replacement before the code is compiled so
SQR(b+5)
translates to
(b+5*b+5) = (6b+5) = 6*3+5 = 23
Regular function calls would calculate the value of the parameter (b+3) before passing it to the function, but since a macro is pre-compiled replacement, the algebraic order of operations becomes very important.
回答2:
Because (3+5*3+5 == 23)
.
Whereas ((3+5)*(3+5)) == 64
.
The best way to do this is not to use a macro:
inline int SQR(int x) { return x*x; }
Or simply write x*x
.
回答3:
Consider the macro replacement using this macro:
#define SQR(x) (x*x)
Using b+5
as the argument. Do the replacement yourself. In your code, SQR(b+5)
will become: (b+5*b+5)
, or (3+5*3+5)
. Now remember your operator precedence rules: *
before +
. So this is evaluated as: (3+15+5)
, or 23
.
The second version of the macro:
#define SQR(x) ((x) * (x))
Is correct, because you're using the parens to sheild your macro arguments from the effects of operator precedence.
This page explaining operator preference for C has a nice chart. Here's the relevant section of the C11 reference document.
The thing to remember here is that you should get in the habit of always shielding any arguments in your macros, using parens.
回答4:
The macro expands to
a = b+5*b+5;
i.e.
a = b + (5*b) + 5;
So 23.
回答5:
After preprocessing, SQR(b+5)
will be expanded to (b+5*b+5)
. This is obviously not correct.
There are two common errors in the definition of SQR
:
do not enclose arguments of macro in parentheses in the macro body, so if those arguments are expressions, operators with different precedences in those expressions may cause problem. Here is a version that fixed this problem
#define SQR(x) ((x)*(x))
evaluate arguments of macro more than once, so if those arguments are expressions that have side effect, those side effect could be taken more than once. For example, consider the result of
SQR(++x)
.By using GCC typeof extension, this problem can be fixed like this
#define SQR(x) ({ typeof (x) _x = (x); _x * _x; })
Both of these problems could be fixed by replacing that macro with an inline function
inline int SQR(x) { return x * x; }
This requires GCC inline extension or C99, See 6.40 An Inline Function is As Fast As a Macro.
回答6:
A macro is just a straight text substitution. After preprocessing, your code looks like:
int main()
{
int a, b=3;
a = b+5*b+5;
printf("%d\n",a);
return 0;
}
Multiplication has a higher operator precedence than addition, so it's done before the two additions when calculating the value for a
. Adding parentheses to your macro definition fixes the problem by making it:
int main()
{
int a, b=3;
a = (b+5)*(b+5);
printf("%d\n",a);
return 0;
}
The parenthesized operations are evaluated before the multiplication, so the additions happen first now, and you get the a = 64
result that you expect.
回答7:
Because Macros are just string replacement and it is happens before the completion process. The compiler will not have the chance to see the Macro variable and its value. For example: If a macro is defined as
#define BAD_SQUARE(x) x * x
and called like this
BAD_SQUARE(2+1)
the compiler will see this
2 + 1 * 2 + 1
which will result in, maybe, unexpected result of
5
To correct this behavior, you should always surround the macro-variables with parenthesis, such as
#define GOOD_SQUARE(x) (x) * (x)
when this macro is called, for example ,like this
GOOD_SQUARE(2+1)
the compiler will see this
(2 + 1) * (2 + 1)
which will result in
9
Additionally, Here is a full example to further illustrate the point
#include <stdio.h>
#define BAD_SQUARE(x) x * x
// In macros alsways srround the variables with parenthesis
#define GOOD_SQUARE(x) (x) * (x)
int main(int argc, char const *argv[])
{
printf("BAD_SQUARE(2) = : %d \n", BAD_SQUARE(2) );
printf("GOOD_SQUARE(2) = : %d \n", GOOD_SQUARE(2) );
printf("BAD_SQUARE(2+1) = : %d ; because the macro will be \
subsituted as 2 + 1 * 2 + 1 \n", BAD_SQUARE(2+1) );
printf("GOOD_SQUARE(2+1) = : %d ; because the macro will be \
subsituted as (2 + 1) * (2 + 1) \n", GOOD_SQUARE(2+1) );
return 0;
}
回答8:
Just enclose each and every argument in the macro expansion into parentheses.
#define SQR(x) ((x)*(x))
This will work for whatever argument or value you pass.
来源:https://stackoverflow.com/questions/10820340/the-need-for-parentheses-in-macros-in-c