PDA

View Full Version : Question about Kochan 2.0 ## "merging operator" Page 247




mdeh
Jan 27, 2009, 09:23 AM
I am not sure if this is a typo or something I simply do not understand....but it is probably the latter. :) Anyway, here is the setup.

The text explains the use of the merging operator "##"
NOTE...although the text uses printf, I believe the same principles apply to NSLog

#define printx(n) printf( "%i\n", x ## n) )

A small test program produces an error.

#include <stdio.h>

#define printx(n) printf( "%i\n", x ## n)

int main (int argc, const char * argv[]) {
printx(FF);
return 0;
}

error: 'xFF' undeclared (first use in this function)

The preprocessed code shows this:

printf( "%i\n", xFF);

My question.
Is the code usable as is, or did the publisher omit the "0" from the define, as in "Ox ## n .

thank you in advance



bbarnhart
Jan 27, 2009, 10:12 AM
I didn't know there was a C++ ## operator. What does that do?

If it were me, I'd switch out that #define with a real function or method.

Your sample doesn't compile because you need a zero before the x

#define printx(n) printf( "%i\n", 0x ## n) )

gnasher729
Jan 27, 2009, 10:20 AM
I am not sure if this is a typo or something I simply do not understand....but it is probably the latter. :) Anyway, here is the setup.

The text explains the use of the merging operator "##"
NOTE...although the text uses printf, I believe the same principles apply to NSLog

#define printx(n) printf( "%i\n", x ## n) )

A small test program produces an error.

#include <stdio.h>

#define printx(n) printf( "%i\n", x ## n)

int main (int argc, const char * argv[]) {
printx(FF);
return 0;
}



The preprocessed code shows this:

printf( "%i\n", xFF);

My question.
Is the code usable as is, or did the publisher omit the "0" from the define, as in "Ox ## n .

thank you in advance

From what you are writing, his example code looks wrong. It should probably have been 0x ## n in the macro, then the preprocessed code would have been

printf( "%i\n", 0xFF);

On the other hand, you could have the following inside main ():


int x1 = 10; int x2 = 20; int x3 = 30;
printx(1); printx(2); printx(3);


which would print the variables x1, x2 and x3 just fine. But I think the preprocessing output shows exactly what ## does: It creates a single symbol from the "x" on the left side and whatever you substituted for "n" on the right side.

And for the second poster: ## is a _preprocessor_ operator, and it works just fine and in exactly the same way in C, C++, Objective-C and Objective-C++.

bbarnhart
Jan 27, 2009, 10:21 AM
The operator ## concatenates two arguments leaving no blank spaces between them:

#define glue(a,b) a ## b
glue(c,out) << "test";

glue(c,out) is translated in the preprocessor to cout

mdeh
Jan 27, 2009, 10:27 AM
On the other hand, you could have the following inside main ():


int x1 = 10; int x2 = 20; int x3 = 30;
printx(1); printx(2); printx(3);


which would print the variables x1, x2 and x3 just fine. But I think the preprocessing output shows exactly what ## does: It creates a single symbol from the "x" on the left side and whatever you substituted for "n" on the right side.


Thanks gnasher. I bet this is what the author meant, as it is repeated quite a few times throughout the text. BTW...this is really neat. I had no idea you could **create** a variable, but it makes sense though. Would you ever use this practically?
Thank you again.

Krevnik
Jan 27, 2009, 12:06 PM
Thanks gnasher. I bet this is what the author meant, as it is repeated quite a few times throughout the text. BTW...this is really neat. I had no idea you could **create** a variable, but it makes sense though. Would you ever use this practically?
Thank you again.

Outside of a macro? I can't think of a single thing.

The key behind the '##' operator is to merge two symbols into one.

'foo ## bar' will always create a 'foobar' symbol. When the compiler comes round, it simply sees 'foobar' and tries to figure out what foobar means using the normal C rules.

Normally, the merge operator has such a small niche use, nobody uses it. I ran across it /once/ in some headers awhile back on Windows, but that was about it.

mdeh
Jan 27, 2009, 12:39 PM
Normally, the merge operator has such a small niche use, nobody uses it. I ran across it /once/ in some headers awhile back on Windows, but that was about it.

Thank you.

lee1210
Jan 27, 2009, 01:54 PM
Thanks gnasher. I bet this is what the author meant, as it is repeated quite a few times throughout the text. BTW...this is really neat. I had no idea you could **create** a variable, but it makes sense though. Would you ever use this practically?
Thank you again.

The only reason i could imagine using it practically is for obfuscation. Precompiler directives can be great, but i have never been a fan because it makes things, to me, less readable/debuggable. if something looks like a function, i am going to try to find the definition, likely with a debugger. When it's actually a macro... whoops, no function, now to grep some headers, trying to find the #define.

I'm not saying they don't have their use, and I suppose it's nice to save a little stack space if you are constantly seeing if a character is special by using a macro instead of making a function call, but if things are that performance intensive you can always in-line functions.

-Lee

skochan
Jan 27, 2009, 08:00 PM
The only reason i could imagine using it practically is for obfuscation. Precompiler directives can be great, but i have never been a fan because it makes things, to me, less readable/debuggable. if something looks like a function, i am going to try to find the definition, likely with a debugger. When it's actually a macro... whoops, no function, now to grep some headers, trying to find the #define.

I'm not saying they don't have their use, and I suppose it's nice to save a little stack space if you are constantly seeing if a character is special by using a macro instead of making a function call, but if things are that performance intensive you can always in-line functions.

-Lee

Yes, it was a stretch for me to even think of a simple example for the ##. It's in the book for completeness in the chapter on the preprocessor. I've never used it in my programs.

Cheers,

Steve Kochan

autorelease
Jan 28, 2009, 02:05 PM
I've seen it used in embedded code. For example, you might define an interrupt handler for the TIMER2_OVERFLOW event with

ISR(TIMER2_OVERFLOW)
{
...
}

ISR might be a macro like

#define ISR(intr) __interrupt void _vect_ ## intr()

which would expand to

__interrupt void _vect_TIMER2_OVERFLOW()
{
...
}

The linker would then recognize __vect_TIMER2_OVERFLOW as the name of an interrupt handler and make sure it gets put at the proper location in the binary. However, the macro hides these details from the programmer, requiring him/her to only know the name of the interrupt.

Token pasting is basically just another glorious way to abuse the preprocessor. (The stringizing operator, #, is by far the best. I should warn you, this is coming from a guy who once used #__VA_ARGS__ in a macro...)

mdeh
Jan 28, 2009, 04:23 PM
I've seen it used in embedded code. For example, you might define an interrupt handler for the TIMER2_OVERFLOW event with

ISR(TIMER2_OVERFLOW)
{
...
}

ISR might be a macro like

#define ISR(intr) __interrupt void _vect_ ## intr()

which would expand to

__interrupt void _vect_TIMER2_OVERFLOW()
{
...
}

The linker would then recognize __vect_TIMER2_OVERFLOW as the name of an interrupt handler and make sure it gets put at the proper location in the binary. However, the macro hides these details from the programmer, requiring him/her to only know the name of the interrupt.

Token pasting is basically just another glorious way to abuse the preprocessor. (The stringizing operator, #, is by far the best. I should warn you, this is coming from a guy who once used #__VA_ARGS__ in a macro...)


Thanks for that. The wonderful thing about forums is that there is often someone who can put all this in perspective. That's part of the fun in posting. Thank you to you and Lee and the others for your views.