Often and often I felt some of the parentheses around arguments in macro definitions were redundant. It’s too inconvenient to parenthesize everything. If I can guarantee the argument needs not be parenthesized, can I omit the parentheses? Or is parenthesizing them all highly recommended?
I came up with this question when I wrote:
#define SWAP_REAL(a, b, temp) do{double temp = a; a = b; b= temp;}while(0)
I think that if an argument appears as an l-value in the macro, the parentheses can be omitted because that means the argument appears with no other operation.
My reasoning is:
The associative priority of assignment symbols is merely higher than comma’s.
You cannot confuse the compiler into thinking that your argument is an expression with a comma in it. For example, SWAP(a, b, b) will not be interpreted successfully as
do{double temp = a, b; a, b = b; b= temp;}while(0)
which can pass compilation.
Am I right? Can anyone give me a counter-example?
In the following example,
#define ADD(a, b) (a += (b))
I think the argument a needn’t be parenthesized. And in this specific case, neither needs the argument b, right?
#JaredPar:
#include <stdio.h>
#define ADD(a, b) (a += (b))
int main(){
int a = 0, b = 1;
ADD(a; b, 2);
return 0;
}
This cannot be compiled successfully on my VS2010. Error C2143: syntax error : missing ')' before ';'
In a nutshell, you don’t need to parenthesize the arguments having appeared as an l-value in the macro, but you are highly recommended to parenthesize them all.
Rules of Macros:
DO NOT make macros with side effects!
As for macros with no side effect, just parenthesize all the arguments without second thought!
As for macros with side effect, stop being obsessive! Parenthesize them all! TnT
Here is one case where it makes a demonstrable difference
ADD(x;y, 42)
With parens this leads to a compilation error but without it leads to code that compiles.
(x;y) += 42; // With parens errors
x;y += 42; // Without parens compiles
This may look like a silly example but it's possible combining macros together can easily lead to strange code expressions like the above.
Why take the chance here? It's just 2 characters
It's unsafe to omit if you use any operator that isn't lowest precedence in your expression. I believe that would be comma.
a op b where op is some operator like +, * etc. will always bind wrong if a contains an expression of low precedence like 1 || 2.
Note I'm not claiming it's safe in those cases. There are more creative ways to break macros. By the way, don't use macros with side effects in the first place. More generally, don't use macros as functions. (See, e.g., Effective C++).
There are macros where you're concatenating elements to make a string (perhaps using the # operator), or building identifiers out of macro arguments using the ## operator. In such cases, you don't parenthesize the arguments.
Also, I think that when the macro arguments are themselves passed as function arguments, then you don't absolutely have to parenthesize them:
#define CALLOC(s, n) calloc(s, n)
You can play fiendish games calling such a macro (CALLOC({3, 4})), but you get what you deserve (a compilation error) — I'm not aware of a way of calling that macro that would work if instead of the macro you wrote the same arguments as a direct call to calloc().
However, if you are using the arguments in most arithmetic expressions, then you do need to wrap them in parentheses:
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
Obviously, if you invoke it with arguments with side effects, then you get what you get. But the arguments won't be misinterpreted as they could be if you wrote:
#define MIN(x, y) x < y ? x : y
and then invoked it as:
MIN(x = 3 * y + 1, y = 2 * x - 2);
The comment by Moon suggests a SWAP_INT macro.
The following code using that macro compiles cleanly when compiled using default options, but fails to compile with -DWITH_PARENTHESES set.
#include <stdio.h>
#ifdef WITH_PARENTHESES
#define SWAP_INT(a, b) do { int temp = (a); (a) = (b); (b) = temp; } while (0)
#else
#define SWAP_INT(a, b) do { int temp = a; a = b; b = temp; } while (0)
#endif
int main(void)
{
int p = 319;
int q = 9923;
int x = 23;
int y = 300;
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(p, q); // OK both ways
SWAP_INT(x, y); // OK both ways
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(x /= y, p *= q); // Compiles without parentheses; fails with them
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
return 0;
}
The output:
p = 319, q = 9923, x = 23, y = 300
p = 9923, q = 319, x = 300, y = 23
p = 41150681, q = 13, x = 0, y = 3165437
That isn't a safe or effective way of swapping integers — the macro without the parentheses is not a good idea.
JFTR: when compiled without -DWITH_PARENTHESES, the line for the macro with the expressions is inscrutable:
do { int temp = x /= y; x /= y = p *= q; p *= q = temp; } while (0);
Normally, a swap macro expects two variable names — or array elements, or structure or union members, or any mix of these. It does not expect to be given arbitrary expressions. The parentheses ensure that the assignment to x /= y (which is not an lvalue) fails; without the parentheses, the expression is interpreted, but it isn't anything like what was intended (if, indeed, anything could be intended when 'swapping' two expressions like that).
Related
This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 5 years ago.
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.
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.
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.
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.
The macro expands to
a = b+5*b+5;
i.e.
a = b + (5*b) + 5;
So 23.
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.
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.
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;
}
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.
I came across a statement in the text C How to Program:
"Expressions with side effects (i.e., variable values are modified) should not be passed to a macro because macro arguments may be evaluated more than once.".
My question is what are expressions with side effects and why should they be not passed to a macro?
The classic example is a macro to calculate the maximum of two value:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Now lets "call" the macro like this:
int x = 5;
int y = 7;
int z = MAX(x++, y++);
Now if MAX was a normal function, we would expect that x and y would be incremented once, right? However because it's a macro the "call" is replaced like this:
int z = ((x++) > (y++) ? (x++) : (y++));
As you see, the variable y will be incremented twice, once in the condition and once as the end-result of the ternary operator.
This is the result of an expression with side-effects (the post-increment expression) and a macro expansion.
On a related note, there are also other dangers with macros. For example lets take this simple macro:
#define MUL_BY_TWO(x) (x * 2)
Looks simple right? But now what if we use it like this:
int result = MUL_BY_TWO(a + b);
That will expand like
int result = (a + b * 2);
And as you hopefully knows multiplication have higher precedence than addition, so the expression a + b * 2 is equivalent to a + (b * 2), probably not what was intended by the macro writer. That is why arguments to macros should be put inside their own parentheses:
#define MUL_BY_TWO(x) ((x) * 2)
Then the expansion will be
int result = ((a + b) * 2);
which is probably correct.
To put it simply a side effect is a write to an object or a read of a volatile object.
So an example of a side effect:
i++;
Here is a use of a side effect in a macro:
#define MAX(a, b) ((a) > (b)) ? (a) : (b))
int a = 42;
int b = 1;
int c;
c = MAX(a, b++);
The danger is contrary to a function where the arguments are passed by value you are potentially modifying b object one or two times (depending on the macro arguments, here one time) in the macro because of the way macros work (by replacing the b++ tokens in the macro definition).
Side Effects can be defined as:
Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).
For example:
int x = y++; //where y is also an int
In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.
Now consider a macro for squaring of an integers :
#define Sq(a) a*a
main()
{
int a=6;
int res=Sq(a);
printf("%d\n",res);
res=Sq(++a);
printf("%d",res);
}
You would expect the output to be
36
49
However the output is
36
64
because macro results in textual replacement and
res becomes (++a)*(++a)
i.e, 8*8=64
Therefore we should not pass arguments with side effects to macros.
(http://ideone.com/mMPQLP)
#define div_ac_power(y,x) *y/x
Shall y be an address? As far as I understand it returns the result of division between a pointer (y) and whatever object is x.
As far as I understand it returns the result of division between a pointer (y) and whatever object is x.
That is probably the intention.
The macro needs more parenthesis to secure it from misuse.
Consider the following cases:
Case 1. Compound parameter:
result= div_ac_power(y,a+b);
which is expanded to:
result = *y/a+b; // This equals (*y/a)+b because of operator precedence.
Case 2. Fooling around:
result= a div_ac_power(y,b); // Note the lack of operator between a and macro
which is expanded to:
result= a*y/b; // This may well be a valid expression depending on the types of a, b, y.
To fix it, you could add parenthesis:
#define div_ac_power(y,x) (*(y)/(x))
Dereference the value pointed-to by y pointer
Divide this value by x value
Same as:
int *y, x; // init them
int z = *y;
int res = z / x;
This question already has answers here:
some error in output in using macro in C
(3 answers)
Closed 9 years ago.
Why doesn't this math work with macros in C?
#include <stdio.h>
#define FOO 6
#define BAR 32
#define MULT FOO * BAR
main() {
int x = 28296;
int y = x / MULT;
printf("%d / %d = %d\n", x, MULT, y);
return 0;
}
The result of this is:
28296 / 192 = 150912
Why isn't it 147? If I set a variable " int mult" equal to MULT, and use the variable in the expression (int y = x / mult) it works as expected.
#define tells the preprocessor to replace the code before compilation, so your line actually says:
int y = x / 6 * 32;
since * and / operators have the same precedence, and are evaluated from left to right, you get (x/6) * 32. The compiler would probably do this calculation for you since x is known to it.
Instead, use parenthesis when defining macros like this
Put a bracket around the macro:
#define MULT (FOO * BAR)
Now, you'll get 147.
The reason getting 150912 is that after macro expansion the expression is equivalent to:
y = 28296 / 6 * 32;
and hence it's evaluated as 28296/6 and then multiplied by32.
As #kevin points out, it's better to put brackets around FOO and BAR as well in general case to avoid surprises like this.
This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 5 years ago.
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.
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.
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.
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.
The macro expands to
a = b+5*b+5;
i.e.
a = b + (5*b) + 5;
So 23.
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.
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.
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;
}
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.