Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

mdeh

macrumors 6502
Original poster
Jan 3, 2009
345
2
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

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

A small test program produces an error.

Code:
#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:

Code:
 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

macrumors 6502a
Jan 16, 2002
824
1
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

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

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
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

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

A small test program produces an error.

Code:
#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:

Code:
 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

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

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

Code:
        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

macrumors 6502a
Jan 16, 2002
824
1
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

macrumors 6502
Original poster
Jan 3, 2009
345
2
On the other hand, you could have the following inside main ():

Code:
        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

macrumors 601
Sep 8, 2003
4,100
1,309
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.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
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

macrumors regular
Apr 1, 2006
150
0
California
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

macrumors regular
Oct 13, 2008
144
0
Achewood, CA
I've seen it used in embedded code. For example, you might define an interrupt handler for the TIMER2_OVERFLOW event with

Code:
ISR(TIMER2_OVERFLOW)
{
  ...
}

ISR might be a macro like

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

which would expand to

Code:
__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

macrumors 6502
Original poster
Jan 3, 2009
345
2
I've seen it used in embedded code. For example, you might define an interrupt handler for the TIMER2_OVERFLOW event with

Code:
ISR(TIMER2_OVERFLOW)
{
  ...
}

ISR might be a macro like

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

which would expand to

Code:
__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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.