Example
#define Echo(a) a
#define Echo(a) (a)
I realize there probably isn’t a significant difference here, but why would you ever want to include the a within parenthesis inside the macro body? How does it alter it?
Example
#define Echo(a) a
#define Echo(a) (a)
I realize there probably isn’t a significant difference here, but why would you ever want to include the a within parenthesis inside the macro body? How does it alter it?
Suppose you have
#define mul(x, y) x * y
What happens if I say:
mul(a + 5, 6); /* a + 5 * 6 */
Now if I slighlty change the macro:
#define mul(x, y) ((x) * (y))
mul(a + 5, 6); /* ((a + 5) * (6)) */
Remember, the arguments aren't evaluated or anything, only textual substitution is performed.
For an explanation about having the entire macro in parentheses, see the link posted by Nate C-K.
foo(bar) (bar)->something, and yes, they are necessary.foo(bar+5). That would be perfectly fine if foo were a function, but if it's a macro without the parenthesis, it'll end up as bar+5->something. Similar if bar is a pointer to a pointer, and you do foo(*bar) which ends up as *bar->something , which is certainly wrong, you'll want (*bar)->somethingJust for the record, I landed from Here How to fix mathematical errors while using macros and I will try to expand this Answer here to fit the Other one.
You are asking about the difference about:
#define Echo( a ) a
#define Echo( a ) ( a )
which is fine as long as you do not understand the macro it self (I am not an expert too :) ).
First of all you already (probably) know that there is Operator Precedence, so there is a huge difference of this two programs:
1):
#include <stdio.h>
#define ADD( a , b ) a + b
int main( void )
{
auto const int a = 5;
auto const int b = 10;
auto const int c = ADD ( 2 + a , 2 + b );
printf( "%d", c );
return 0;
}
Output:
19
and:
#include <stdio.h>
#define ADD( a , b ) ( a ) + ( b )
int main( void )
{
auto const int a = 5;
auto const int b = 10;
auto const int c = ADD ( a , b );
printf( "%d", c );
return 0;
}
Output:
15
Now lets preplace + with *:
#define ADD( a, b ) a * b
The compiler treats a * b like for example a == 5 and b == 10 which does 5 * 10.
But, when you say:
ADD ( 2 + a * 5 + b )
Like here:
#include <stdio.h>
#define ADD( a , b ) ( a ) * ( b )
int main( void )
{
auto const int a = 5;
auto const int b = 10;
auto const int c = ADD ( 2 + a , 5 + b );
printf( "%d", c );
return 0;
}
You get 105, because the operator precedence is involved and treats
2 + b * 5 + a
as
( 2 + 5 ) * ( 5 + 10 )
which is
( 7 ) * ( 15 ) == 105
But when you do:
#include <stdio.h>
#define ADD( a, b ) a * b
int main( void )
{
auto const int a = 5;
auto const int b = 10;
auto const int c = ADD ( 2 + a , 5 + b );
printf( "%d", c );
return 0;
}
you get 37 because of
2 + 5 * 5 + 10
which means:
2 + ( 5 * 5 ) + 10
which means:
2 + 25 + 10
Short answer, there is a big difference between:
#define ADD( a , b ) a * b
and
#define ADD( a , b ) ( a ) * ( a )
auto before variables? It is totally redundantauto in this examples?auto on all the variables, but it is bad style because the preferred style in C is not to write auto ever. Similarly, omitting return 0; at the end of main is correct, but bad style; preferred style is not to leave that out. Going against the preferred style makes it harder for other people to read your code, and that in itself is enough reason not to do it.auto means something completely different (and actually useful) in C++, so writing it in C code may mislead people into thinking that it's meant to be compiled as C++; omitting return 0; in main was UB prior to C99 and is also a weird special case, not consistent with the rest of the language. But not all style rules have objective rationales, and you should adhere to them anyway. Because readability.auto takes on a life of its own, rather like it already has done in C++. I firmly agree with the sentiment that C code written at any time in the last 40 years should not use the keyword auto. I'm going to be cautious about using auto even in code intended for C23 — the possibilities for misunderstanding are too large for my comfort (plus I'm struggling to get our code base to use C11 at work; we have at least moved to C99 now).