Question about Kochan 2.0 ## "merging operator" Page 247

Discussion in 'Mac Programming' started by mdeh, Jan 27, 2009.

  1. macrumors 6502

    Joined:
    Jan 3, 2009
    #1
    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
     
  2. macrumors 6502a

    bbarnhart

    Joined:
    Jan 16, 2002
    Location:
    Stilwell, Kansas
    #2
    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) )
     
  3. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    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++.
     
  4. macrumors 6502a

    bbarnhart

    Joined:
    Jan 16, 2002
    Location:
    Stilwell, Kansas
    #4
    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
     
  5. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #5

    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.
     
  6. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #6
    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.
     
  7. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #7
    Thank you.
     
  8. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #8
    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
     
  9. macrumors regular

    Joined:
    Apr 1, 2006
    Location:
    California
    #9
    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
     
  10. macrumors regular

    Joined:
    Oct 13, 2008
    Location:
    Achewood, CA
    #10
    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...)
     
  11. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #11

    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.
     

Share This Page