

...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 http://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 http://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
> http://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
-------------------------------------------------------