Tips on writing C macros
commonsense4commonpeople.net
commonsense4commonpeople.net
Also, more useful (GCC only, though) than just enclosing parameters in parentheses, because it makes macros side-effect safe: http://en.wikipedia.org/wiki/C_preprocessor#Multiple_evaluat... Of course, in the macro in the article, the first 2 parameters need to be modifiable lvals anyway, so for those the whole deal with parentheses and the typeof construct is a moot point.
I'd write the proposed macro as:
#define MYMACRO(a,b,c) \
({ \
typeof (c) _c = (c); \
a = b + _c; \
b = _c * 2; \
})Admittedly I have little experience with compilers other than GCC, but all things considered, I'd shy away from using anything but really basic macros without the compound-statement-in-parens and typeof() extensions that GCC provides.
Perhaps I spoke too harshly, calling it "nonsense". :-)
I was wrong. It's the more platform independent way to do things.
For code that's only ever going to be compiled with GCC, though, the statement expression method is cleaner, I think.
It's much nicer to be able to call "MYMACRO(1, 2, 3);" than it is to have to remember to leave the semi-colon off.
"This construct is not legal ANSI C; both the typeof keyword, and the construct of placing a compound statement within parentheses, are non-standard extensions implemented in the popular GNU C compiler (GCC)."
MYMACRO(x,y,x+y)
with your inclusion of typeof()?As an example:
int main () {
typeof (1.0f + 10) a;
int * b = &a;
}
----- $ g++ test.c
test.c: In function ‘int main()’:
test.c:3: error: cannot convert ‘float*’ to ‘int*’ in initialization
I'm using g++ because it actually spits out type information for incompatible pointers- probably something having to do with it being an error in C++ but valid in C (with a warning, at least in GCC).Deleted comment
#include <stdio.h>
#define MYMACRO(a,b,c) \
({ \
typeof (c) _c = (c); \
a = b + _c; \
b = _c * 2; \
})
int main() {
int a = 0, b = 0;
if (1)
MYMACRO(a,b,1);
else
MYMACRO(a,b,2);
printf("%d, %d\n", a, b);
}
----- $ gcc -o test test.c
$ ./test
1, 2
Edit: Just for context: this was responding to a post pointing out that the do-while construct allows you to use a semi-colon after the macro invocation.#define ADD_ONE(a) ({ a + 1; })
x = ADD_ONE(2);
Wouldn't any decent optimizing compiler eliminate those common subexpressions? That's one of the basics, isn't it?
Of course, if you're in a tight enough loop to worry about that, check the assembly by hand.
Tip 2, see tip 1