...making Linux just a little more fun!
Oscar Laycock [oscar_laycock at yahoo.co.uk]
I recently discovered you could "stringize" a whole C++ or C statement with the pre-processor. For example:
#define TRACE(s) cerr << #s << endl; s or: #define TRACE(s) printf("%s\n", #s); s .... TRACE(*p = '\0'); p--;
(I found this in "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel, available for free at https://www.mindview.net. By the way, it seems a good introduction to C++ for C programmers with lots of useful exercises. There is also a free, but slightly old, version of the official Qt book (the C++ framework used in KDE), at https://www.qtrac.eu/C++-GUI-Programming-with-Qt-4-1st-ed.zip. It is a bit difficult for a C++ beginner, and somewhat incomplete without the accompanying CD, but rewarding none the less.)
Bruce Eckel adds: "of course this kind of thing can cause problems, especially in one-line for loops:
for(int i = 0; i < 100; i++) TRACE(f(i));
Because there are actually two statements in the TRACE( ) macro, the one-line for loop executes only the first one. The solution is to replace the semicolon with a comma in the macro."
However, when I try this with a declaration. I get a compiler error:
TRACE(char c = *p); s.cpp:17: error: expected primary-expression before 'char' s.cpp:17: error: expected `;' before 'char'
I'm not sure exactly why!?
Neil Youngman [ny at youngman.org.uk]
On Monday 05 January 2009 14:06:12 Oscar Laycock wrote:
> I recently discovered you could "stringize" a whole C++ or C statement with > the pre-processor. For example: > > #define TRACE(s) cerr << #s << endl; s > or: > #define TRACE(s) printf("%s\n", #s); s > > .... > TRACE(*p = '\0'); > p--; > > (I found this in "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel, > available for free at www.mindview.net. By the way, it seems a good > introduction to C++ for C programmers with lots of useful exercises. There > is also a free, but slightly old, version of the official Qt book (the C++ > framework used in KDE), at > https://www.qtrac.eu/C++-GUI-Programming-with-Qt-4-1st-ed.zip. It is a bit > difficult for a C++ beginner, and somewhat incomplete without the > accompanying CD, but rewarding none the less.) > > Bruce Eckel adds: "of course this kind of thing can cause problems, > especially in one-line for loops: > > for(int i = 0; i < 100; i++) > TRACE(f(i)); > > Because there are actually two statements in the TRACE( ) macro, the > one-line for loop executes only the first one. The solution is to replace > the semicolon with a comma in the macro."
Better yet, always use braces with your for/if/else/while statements, even if there is only a single line now. It avoids later editing errors and problems with "too clever by half macros.
> However, when I try this with a declaration. I get a compiler error: > > TRACE(char c = *p); > > s.cpp:17: error: expected primary-expression before 'char' > s.cpp:17: error: expected `;' before 'char' > > I'm not sure exactly why!?
It's obvious. Do the substitution and you get:
cerr << char c = *p << endl; char c = *p;
which is obviously garbage. It's never going to work where the statement is a declaration.
HTH
Neil Youngman
Neil Youngman [Neil.Youngman at youngman.org.uk]
---------- Forwarded Message ----------
Subject: Re: [TAG] tct: 2-cent Tip - Stringizing a C statement Date: Tuesday 06 January 2009 From: Neil Youngman <ny@youngman.org.uk> To: oscar_laycock@yahoo.co.ukOn Tuesday 06 January 2009 13:25:23 Oscar Laycock wrote:
> ---Isn't it:cerr << "char c = *p" << endl, char c = *p;
> I thought it was > because the comma operator separates statements not declarations. For > example:for (i = 0; i = 0; ; i++, j++) {}I'm learning C++ so I can't say > for sure!
Yes. I missed out the stringizing of the part inside cerr. It is still garbage because, as you say, "the comma operator separates statements not declarations".
HTH
Neil
-------------------------------------------------------