5 ms·
What's that nonsense with the do-while loop? Why not just enclose the macro body in both curly braces and then in parentheses? Also, more useful (GCC only, tho
by paulbaumgart 17y ago
What's that nonsense with the do-while loop? Why not just enclose the macro body in both curly braces and then in parentheses?
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_evaluation_of_side_effects 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; \
})
- deleted 17y ago[deleted]
- paulbaumgart 17y agoSame with what I suggested: #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.
- doug11235 17y agoAnd another feature I like about ({ }) macros (anyone know the proper name here?) is you can return values. Clearly more useful in an example a bit more complex but... #define ADD_ONE(a) ({ a + 1; }) x = ADD_ONE(2);
- tedunangst 17y agoThey are called statement expressions.
- greyboy 17y agoExcuse my lack of C knowledge, but using your proposed macro, what would be the result of calling: MYMACRO(x,y,x+y) with your inclusion of typeof()?
- paulbaumgart 17y agotypeof is pretty smart. Since in C all types are known at compile-time, the compiler can put in there in whatever type typeof's parameter resolves to- even if it's an expression. 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).
- michaelfairley 17y agoWith your code, placing a semicolon after the macro leads to a compile error. Semicolons are not valid after arbitrary blocks, but it is acceptable to place them after do-while loops. 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.
- paulbaumgart 17y agoIt compiles fine on GCC. For other compilers, the Wikipedia page I linked offers the caveat: "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)."
- tb 17y agoThe do-while "nonsense" is a pretty standard construct, so much so that I'd never seen your approach - which I admit looks nicer. How well is that supported across different compilers? Is it part of C99, for example?
- paulbaumgart 17y agoNo, it's not in C99: http://www.redhatrenewals.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/c-extensions.html http://www.redhatrenewals.com/docs/manuals/enterprise/RHEL-4... 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". :-)
- paulbaumgart 17y agoSo, just to follow up, I saw that the OCUnit macros ( http://www.sente.ch/software/ocunit/ http://www.sente.ch/software/ocunit/ ) are all using defined using the do...while(0) guard. 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.
- tedunangst 17y agoIt's only supported by gcc and some edg based compilers. edg has trouble with it in some c++ code. Just think of how adding this complicates your grammar.
- gchpaco 17y agoCurly braces and then parens is a GCC extension. If you're going to do complicated macrology, GCC is the way to go because of typeof and a bunch of related extensions designed to make macro use work. But it's still a staggering amount of effort and not worth it in the long run.
- abecedarius 17y agoThis ({ ... }) syntax was not in the original ANSI C or K&R. Is it in C99 or in GNU C only? I've only ever seen it in GNU C.
- sketerpot 17y agoWhat if you already have a variable called _c and you pass it to MYMACRO? Is there any way of generating a guaranteed-unique symbol, similar to GENSYM in lisp?