Macro arguments – be careful with them
Debugging applications that has lots of macro()s are considered to be very tough. And it seems that most people prefer to expand macros as blocks with new temporary variables. Let us try to find out why one would not prefer to use the macro arguments directly in their block code. Consider for example a macro that returns the square of a number. Normally, any careful programmer would write the macro as given below:
#define square(a) ((a) * (a))
And yes, what the macro will do is precisely what we would expect of it. The above macro is just perfect as long as what we provide as argument to it is a plain value – like a variable or a constant. For example:
int i = 10;
printf("square : %d\n", square(i));
would print 100 as we had desired. The preprocessed text is just the expression ((i) * (i)). This will continue to go on fine until you start to do some fancy tricks like the following:
int i = 10;
printf("square : %d\n", square(++i));
Obviously, what we had expected was the square of 11 but the one we got was that of 12(for gcc, can change for others). So, how did that happen? Yes.. after preprocessing, your code became ((++i) * (++i)) and according to gcc, the values of i used in the expression is that after doing all the pre-increments in the expression. Since there are 2 pre-increments, the compiler takes the expression as ((12) * (12)).
Apart from the wrong answer we got, another side effect that we have to acknowledge is that the variable i has been incremented twice after calling square(), instead of just once. So, what is the solution for such a situation? Simple, use only dummy variables for computations:
#define square(a) ({ typeof(a) var=(a); var*var; })
so thats it ! you dont need to worry at all about the new variable that you have created above – compilers are intelligent enough to nullify its overhead. Well, so now our problem is solved
we can create new ones