Shabeer
its all about me
Monday 26 January 2015
sdf
#define ADD_FIVE(a) (a) + 5
int x = ADD_FIVE(3) * 3;
// this expands to (3) + 5 * 3, so 5 * 3 is evaluated first
// Now x is 18, not 24!
To fix this, you generally want to surround the whole macro body with parentheses to prevent the surrounding context from affecting the macro body.
#define ADD_FIVE(a) ((a) + 5)
int x = ADD_FIVE(3) * 3;
On the other hand, if you have a multiline macro that you are using for its side effects, rather than to compute a value, you probably want to wrap it within curly braces so you don't have problems when using it following an if statement.
// We use a trick involving exclusive-or to swap two variables
#define SWAP(a, b) a ^= b; b ^= a; a ^= b;
int x = 10;
int y = 5;
// works OK
SWAP(x, y);
// What happens now?
if(x < 0)
SWAP(x, y);
When SWAP is expanded in the second example, only the first statement, a ^= b, is governed by the conditional; the other two statements will always execute. What we really meant was that all of the statements should be grouped together, which we can enforce using curly braces:
#define SWAP(a, b) {a ^= b; b ^= a; a ^= b;}
Now, there is still a bit more to our story! What if you write code like so:
#define SWAP(a, b) { a ^= b; b ^= a; a ^= b; }
int x = 10;
int y = 5;
int z = 4;
// What happens now?
if(x <0 data-blogger-escaped-font="">
SWAP(x, y);
else
SWAP(x, z);
Then it will not compile because semicolon after the closing curly brace will break the flow between if and else. The solution? Use a do-while loop:
#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while ( 0 )
int x = 10;
int y = 5;
int z = 4;
// What happens now?
if(x <0 data-blogger-escaped-font="">
SWAP(x, y);
else
SWAP(x, z);
Now the semi-colon doesn't break anything because it is part of the expression. (By the way, note that we didn't surround the arguments in parentheses because we don't expect anyone to pass an expression into swap!)
By now, you've probably realized why people don't really like using macros. They're dangerous, they're picky, and they're just not that safe. Perhaps the most irritating problem with macros is that you don't want to pass arguments with "side effects" to macros. By side effects, I mean any expression that does something besides evaluate to a value. For instance, ++x evaluates to x+1, but it also increments x. This increment operation is a side effect.
The problem with side effects is that macros don't evaluate their arguments; they just paste them into the macro text when performing the substitution. So something like
#define MAX(a, b) ((a) < (b) ? (b) : (a))
int x = 5, y = 10;
int z = MAX(x++, y++);
will end up looking like this:
int z = (x++ < y++ ? y++ : x++)
The problem here is that y++ ends up being evaluated twice! The nasty consequence is that after this expression, y will have a value of 12 rather than the expected 11. This can be a real pain to debug!
postu
#define ADD_FIVE(a) (a) + 5
int x = ADD_FIVE(3) * 3;
// this expands to (3) + 5 * 3, so 5 * 3 is evaluated first
// Now x is 18, not 24!
To fix this, you generally want to surround the whole macro body with parentheses to prevent the surrounding context from affecting the macro body.
#define ADD_FIVE(a) ((a) + 5)
int x = ADD_FIVE(3) * 3;
On the other hand, if you have a multiline macro that you are using for its side effects, rather than to compute a value, you probably want to wrap it within curly braces so you don't have problems when using it following an if statement.
// We use a trick involving exclusive-or to swap two variables
#define SWAP(a, b) a ^= b; b ^= a; a ^= b;
int x = 10;
int y = 5;
// works OK
SWAP(x, y);
// What happens now?
if(x < 0)
SWAP(x, y);
When SWAP is expanded in the second example, only the first statement, a ^= b, is governed by the conditional; the other two statements will always execute. What we really meant was that all of the statements should be grouped together, which we can enforce using curly braces:
#define SWAP(a, b) {a ^= b; b ^= a; a ^= b;}
Now, there is still a bit more to our story! What if you write code like so:
#define SWAP(a, b) { a ^= b; b ^= a; a ^= b; }
int x = 10;
int y = 5;
int z = 4;
// What happens now?
if(x <0 font="">
SWAP(x, y);
else
SWAP(x, z);
Then it will not compile because semicolon after the closing curly brace will break the flow between if and else. The solution? Use a do-while loop:
#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while ( 0 )
int x = 10;
int y = 5;
int z = 4;
// What happens now?
if(x <0 font="">
SWAP(x, y);
else
SWAP(x, z);
Now the semi-colon doesn't break anything because it is part of the expression. (By the way, note that we didn't surround the arguments in parentheses because we don't expect anyone to pass an expression into swap!)
By now, you've probably realized why people don't really like using macros. They're dangerous, they're picky, and they're just not that safe. Perhaps the most irritating problem with macros is that you don't want to pass arguments with "side effects" to macros. By side effects, I mean any expression that does something besides evaluate to a value. For instance, ++x evaluates to x+1, but it also increments x. This increment operation is a side effect.
The problem with side effects is that macros don't evaluate their arguments; they just paste them into the macro text when performing the substitution. So something like
#define MAX(a, b) ((a) < (b) ? (b) : (a))
int x = 5, y = 10;
int z = MAX(x++, y++);
will end up looking like this:
int z = (x++ < y++ ? y++ : x++)
The problem here is that y++ ends up being evaluated twice! The nasty consequence is that after this expression, y will have a value of 12 rather than the expected 11. This can be a real pain to debug!
0>0>