preprocessor q: impossible macro?

E

Eric

Hello all,
I've got this line of given code (cannot change this; wizard-generated, but
value may change someday):
#define IDB_BUTTON 225

Somewhere in the code I found / need this:
.....somefunction("#225")....

This string in the function call is the same number like in the define, but
the constant wasn't used. Because for future changes and for readability I
wanted to create this string with a preprocessor macro like this:
.....somefunction(MYMACRO(IDB_BUTTON))....

I didn't get such a macro to work. I tried:
#define MYMACRO(num) "#" #num
but this only yields to
.....somefunction("#" "IDB_BUTTON")....
I also tried with the token-pasting operator (##) etc.

Is this possible at all?
Eric
 
V

Victor Bazarov

Eric said:
I've got this line of given code (cannot change this; wizard-generated, but
value may change someday):
#define IDB_BUTTON 225

Somewhere in the code I found / need this:
....somefunction("#225")....

This string in the function call is the same number like in the define, but
the constant wasn't used. Because for future changes and for readability I
wanted to create this string with a preprocessor macro like this:
....somefunction(MYMACRO(IDB_BUTTON))....

I didn't get such a macro to work. I tried:
#define MYMACRO(num) "#" #num
but this only yields to
....somefunction("#" "IDB_BUTTON")....
I also tried with the token-pasting operator (##) etc.

Is this possible at all?

Yes, you need an indirect "stringizing" macro for that.

#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

V
 
C

Charles Mills

Victor said:
Yes, you need an indirect "stringizing" macro for that.

#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

V

The above solution does not compile. Token pasting is not necessary
since adjacent string literals are pasted.

#define STR(x) #x
#define MYMACRO(num) "#" STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

-Charlie
 
V

Victor Bazarov

Charles said:
Victor Bazarov wrote:
[..]
#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

V


The above solution does not compile. [..]

On what compiler? What is the error message?

V
 
C

Charles Mills

Victor said:
Charles said:
Victor Bazarov wrote:
[..]
#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

V


The above solution does not compile. [..]

On what compiler? What is the error message?

V

gcc
pasting ""#"" and "STR" does not give a valid preprocessing token

The standard says that token pasting must result in a valid C token.

-Charlie
 
V

Victor Bazarov

Charles said:
Victor said:
Charles said:
Victor Bazarov wrote:
[..]

#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

V


The above solution does not compile. [..]

On what compiler? What is the error message?

V


gcc
pasting ""#"" and "STR" does not give a valid preprocessing token

The standard says that token pasting must result in a valid C token.

I don't have a copy of the _old_ C standard handy, but the C++ Standard
has the sub-clause 16.3.1 (and C99 has 6.10.3.1), which essentially says
that operators # and ## are only acted upon after *all* substitutions have
taken place. So, your version of gcc is *buggy* if it doesn't compile the
code I posted, it ought to rescan the substitution (according to 16.3.4)
until no macro is left unsubstituted.

IOW, the result of 'MYMACRO(IDB_BUTTON)' yields

"#" ## STR(225)

which in turn, after rescanning yields

"#" ## #225

which then yields

"#" ## "225"

And two tokens are concatenated. Relying on the catenation of strings
is OK, I suppose. I just don't like it, and use ## explicitly.

BTW, Comeau online thingy gets it right in all modes, VC++ gets it right,
and I am betting, countless others get it right, I am just too lazy to
check.

V
 
R

Rob Williscroft

Victor Bazarov wrote in @newsread1.mlpsca01.us.to.verio.net in comp.lang.c++:
Yes, you need an indirect "stringizing" macro for that.

#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

You don't need the ## above as strings concatinate anyway:

#define MYMACRO(num) ( "#" STR(num) )

Also AIUI using ## to concatinate 2 tokens that don't then
make a valid preprocessor token is illegal.
#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

Rob.
 
V

Victor Bazarov

Rob said:
Victor Bazarov wrote in @newsread1.mlpsca01.us.to.verio.net in comp.lang.c++:




You don't need the ## above as strings concatinate anyway:

#define MYMACRO(num) ( "#" STR(num) )

Also AIUI using ## to concatinate 2 tokens that don't then
make a valid preprocessor token is illegal.

I don't understand this sentence. Perhaps you could rephrase...
Also, see my reply to Charles Mills. The code is valid.

V
 
M

Me

Eric said:
Hello all,
I've got this line of given code (cannot change this; wizard-generated, but
value may change someday):
#define IDB_BUTTON 225

Somewhere in the code I found / need this:
....somefunction("#225")....

This string in the function call is the same number like in the define, but
the constant wasn't used. Because for future changes and for readability I
wanted to create this string with a preprocessor macro like this:
....somefunction(MYMACRO(IDB_BUTTON))....

I didn't get such a macro to work. I tried:
#define MYMACRO(num) "#" #num
but this only yields to
....somefunction("#" "IDB_BUTTON")....
I also tried with the token-pasting operator (##) etc.

Is this possible at all?

Yes (see the other responses to this thread) but if you're programming
Windows like I suspect you are, you don't even need to do this, you can
just use the MAKEINTATOM(IDB_BUTTON) macro provided in windows.h which
does something more efficient based on a feature of the OS.
 
R

Rob Williscroft

Victor Bazarov wrote in @newsread1.mlpsca01.us.to.verio.net in comp.lang.c++:
I don't understand this sentence. Perhaps you could rephrase...

Here's n example of the use of ## pehraps it will help:

#include <iostream>
#include <ostream>

#define STR( x ) #x
#define XSTR( x ) "X" STR( x )

#define PSTR_2( x, y ) x ## STR( y )
#define PSTR( x, y ) PSTR_2(x, y )


int main()
{
std::cout << STR(i) << std::endl;
std::cout << PSTR(X,i) << std::endl;
}

The 2 tokens you are attempting to paste are " and STR, "STR
is not a valid preprocessor token.
Also, see my reply to Charles Mills. The code is valid.

You can find this in the Standard

16.3.3 The ## operator

...

If the result is not a valid preprocessing token,
the behavior is undefined



Rob.
 
V

Victor Bazarov

Rob said:
Victor Bazarov wrote in @newsread1.mlpsca01.us.to.verio.net in comp.lang.c++:




Here's n example of the use of ## pehraps it will help:

#include <iostream>
#include <ostream>

#define STR( x ) #x
#define XSTR( x ) "X" STR( x )

#define PSTR_2( x, y ) x ## STR( y )
#define PSTR( x, y ) PSTR_2(x, y )


int main()
{
std::cout << STR(i) << std::endl;
std::cout << PSTR(X,i) << std::endl;
}

The 2 tokens you are attempting to paste are " and STR, "STR
is not a valid preprocessor token.




You can find this in the Standard

16.3.3 The ## operator

...

If the result is not a valid preprocessing token,
the behavior is undefined

Yes, how is that applicable here? Did you read my reply to Charles?

V
 
R

Rob Williscroft

Victor Bazarov wrote in @newsread1.mlpsca01.us.to.verio.net in comp.lang.c++:
Yes, how is that applicable here? Did you read my reply to Charles?

Yes, your argument is incorrect, reread 16.3.3, the "*all*" in
your paraphrasing ("essentialy says ...") is wrong. Only macro
paramiters are expanded before ## is used to paste tokens.

Not that that would matter anyway, the token on the left of the ##
is a quote ("), and a quote is a single token, its *never* part
of another token. Which violates the above cut&paste from the
Standard.

Rob.
 
C

Charles Mills

Rob said:
Victor Bazarov wrote in @newsread1.mlpsca01.us.to.verio.net in comp.lang.c++:


Yes, your argument is incorrect, reread 16.3.3, the "*all*" in
your paraphrasing ("essentialy says ...") is wrong. Only macro
paramiters are expanded before ## is used to paste tokens.

Not that that would matter anyway, the token on the left of the ##
is a quote ("), and a quote is a single token, its *never* part
of another token. Which violates the above cut&paste from the
Standard.

Rob.

I think you mean a string literal is a single token, right?
So pasting two string literals like:
"a" ## "b"
would create the token:
"a""b"
which is an invalid token.
Another example would be pasting the tokens c and ++
c ## ++
creates the token
c++
which is not a valid C token :)

-Charlie
 
R

Rob Williscroft

Charles Mills wrote in @g49g2000cwa.googlegroups.com in comp.lang.c++:
I think you mean a string literal is a single token, right?

I didn't, but I was wrong :(. Thanks for the correction.
So pasting two string literals like:
"a" ## "b"
would create the token:
"a""b"
which is an invalid token.

Not so sure about that, which is maybe why Victor, believes
his interpritation is correct, if valid and *all* tokens were
expanded prior to ## doing its thing, then Victors code would
be valid. But that isn't what the Standard says, but it possibly
is how many C++ preprocessors currently work.
Another example would be pasting the tokens c and ++
c ## ++
creates the token
c++
which is not a valid C token :)

Agreed.

Rob.
 
G

Greg

Victor said:
Charles said:
Victor said:
Charles Mills wrote:

Victor Bazarov wrote:
[..]

#define STR(x) #x
#define MYMACRO(num) "#" ## STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

V


The above solution does not compile. [..]

On what compiler? What is the error message?

V

IOW, the result of 'MYMACRO(IDB_BUTTON)' yields

"#" ## STR(225)

which in turn, after rescanning yields

"#" ## #225

which then yields

"#" ## "225"

And two tokens are concatenated. Relying on the catenation of strings
is OK, I suppose. I just don't like it, and use ## explicitly.

BTW, Comeau online thingy gets it right in all modes, VC++ gets it right,
and I am betting, countless others get it right, I am just too lazy to
check.

V

Your code may compile but its output is not correct. The preprocessed
output of the printf statement in the above example is:

std::printf("Got %s\n", "#""IDB_BUTTON" );

whereas the corrrect result would be:

std::printf("Got %s\n", "#225" );

or its equivalent. Omitting the ## token pasting operator does yield
the correct result. Another solution would be to use slightly different
macros:

#define STR(num) "#" ## #num
#define MYMACRO(num) STR(num)

In both of these cases the preprocessed output is:

std::printf("Got %s\n", "#" "225" );

As others have noted, the compiler will concatenate adjacent string
literals, making this output match the correct result;

Greg
 
H

Heinz Ozwirk

Eric said:
Hello all,
I've got this line of given code (cannot change this; wizard-generated,
but value may change someday):
#define IDB_BUTTON 225

Somewhere in the code I found / need this:
....somefunction("#225")....

If those defines and functions are what I think they are, you should have a
look at MAKEINTRESOURCE in your compiler's/API's documentation.

Heinz
 
N

noblesantosh

Charles said:
The above solution does not compile. Token pasting is not necessary
since adjacent string literals are pasted.

#define STR(x) #x
#define MYMACRO(num) "#" STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

-Charlie

Charlie, your code doesn't compile ...

[ysantosh@IndLexx testprogs]$ gcc prog1.c
prog1.c:10:28: warning: pasting ""#"" and "STR" does not give a valid
preprocessing token
prog1.c: In function `main':
prog1.c:10: parse error before `STR'

--santosh
 
N

noblesantosh

Charles said:
The above solution does not compile. Token pasting is not necessary
since adjacent string literals are pasted.

#define STR(x) #x
#define MYMACRO(num) "#" STR(num)

#define IDB_BUTTON 225

#include <stdio.h>

int main(void) {
printf("Got %s\n", MYMACRO(IDB_BUTTON));
}

-Charlie

Charlie, your code doesn't compile ...

[ysantosh@IndLexx testprogs]$ gcc prog1.c
prog1.c:10:28: warning: pasting ""#"" and "STR" does not give a valid
preprocessing token
prog1.c: In function `main':
prog1.c:10: parse error before `STR'

--santosh
 
J

Jirka Klaue

Victor Bazarov:
....
IOW, the result of 'MYMACRO(IDB_BUTTON)' yields

"#" ## STR(225)

which in turn, after rescanning yields

"#" ## #225

which then yields

"#" ## "225"

And two tokens are concatenated. Relying on the catenation of strings
is OK, I suppose. I just don't like it, and use ## explicitly.

The concatenation with ## yields "#""225" which is not a valid
preprocessing token.
BTW, Comeau online thingy gets it right in all modes, VC++ gets it right,
and I am betting, countless others get it right, I am just too lazy to
check.

It's not relevant what any compiler considers "right".

Jirka
 
E

Eric

Hi Victor, Charles, Greg, Jirka, noblesantosh, Rob

Thanks for your valuable feedback and the infos about tokens. I don't know
what's the exact difference to what I have made, but like you said, it's
obviously impossible to do it with one single macro. Probably that's why I
couldn't get my version to work.

I know omitted the ## like mentioned in the thread, which yields to "#"
"225", which works fine.

Follow-up question: Is it possible to create a macro that yields to exactly
"#225" after preprocessing?

Eric
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top