I have a function that I need to macro'ize. The function contains temp variables and I can't remember if there are any rules about use of temporary variables in macro substitutions.
long fooAlloc(struct foo *f, long size)
{
long i1, i2;
double *data[7];
/* do something */
return 42;
}
MACRO Form:
#define ALLOC_FOO(f, size) \
{\
long i1, i2;\
double *data[7];\
\
/* do something */ \
}
Is this ok? (i.e. no nasty side effect - other than the usual ones : not "type safe" etc). BTW, I know "macros are evil" - I simply have to use it in this case - not much choice.
C macros are only (relatively simple) textual substitutions.
So the question you are maybe asking is: can I create blocks (also called compound statements) in a function like in the example below?
and the answer is yes.
Now as @DietrichEpp mentioned it in his answer, if the macro is a compound statement like in your example, it is a good practice to enclose the macro statements with
do { ... } while (0)
rather than just{ ... }
. The link below explains what situation thedo { ... } while (0)
in a macro tries to prevent:http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html
Also when you write a function-like macro always ask yourself if you have a real advantage of doing so because most often writing a function instead is better.
First, I strongly recommend inline functions. There are very few things macros can do and they can't, and they're much more likely to do what you expect.
One pitfall of macros, which I didn't see in other answers, is shadowing of variable names.
Suppose you defined:
And someone used it this way:
After preprocessing, the code is:
This doesn't work, because the internal temp shadows the external.
The common solution is to call the variable
__temp
, assuming nobody will define a variable using this name (which is a strange assumption, given that you just did it).They can. They often shouldn't.
Why does this function need to be a macro? Could you inline it instead?
Eldar's answer shows you most of the pitfalls of macro programming and some useful (but non standard) gcc extension.
If you want to stick to the standard, a combination of macros (for genericity) and
inline
functions (for the local variables) can be useful.In such a case using
sizeof
only evaluates the expression for the type at compile time and not for its value, so this wouldn't evaluateF
twice.BTW, "sizes" should usually be typed with
size_t
and not withlong
or similar.Edit: As to Jonathan's question about
inline
functions, I've written up something about theinline
model of C99, here.A not perfect solution: (does not work with recursive macros, for example multiple loops inside each other)
will become after running the preprocessor:
There are only two conditions under which it works in any "reasonable" way.
The macro doesn't have a return statement. You can use the
do while
trick.You only target GCC.
It would help if you explain why you have to use a macro (does your office have "macro mondays" or something?). Otherwise we can't really help.