Tux

...making Linux just a little more fun!

2-cent Tip - Stringizing a C statement

Oscar Laycock [oscar_laycock at yahoo.co.uk]


Mon, 5 Jan 2009 14:06:12 +0000 (GMT)

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!?


Top    Back


Neil Youngman [ny at youngman.org.uk]


Mon, 5 Jan 2009 14:28:47 +0000

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


Top    Back


Neil Youngman [Neil.Youngman at youngman.org.uk]


Tue, 6 Jan 2009 14:16:34 +0000

---------- Forwarded Message ----------

Subject: Re: [TAG] tct: 2-cent Tip - Stringizing a C statement
Date: Tuesday 06 January 2009
From: Neil Youngman <[email protected]>
To: [email protected]
On 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

-------------------------------------------------------


Top    Back