Thread: ## operator

  1. #1
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99

    ## operator

    Hello,

    I'm slightly puzzled by the following example from Section 6.10.3.3 of the C99 Standard (this one here http://www.open-std.org/JTC1/SC22/WG...cs/n1256.pdf):

    "EXAMPLE In the following fragment:

    Code:
    #define hash_hash # ## #
    #define mkstr(a) # a
    #define in_between(a) mkstr(a)
    #define join(c, d) in_between(c hash_hash d)
    char p[] = join(x, y); // equivalent to
    // char p[] = "x ## y";
    The expansion produces, at various stages:

    Code:
    join(x, y)
    in_between(x hash_hash y)
    in_between(x ## y)
    mkstr(x ## y)
    "x ## y"
    In other words, expanding hash_hash produces a new token, consisting of two adjacent sharp signs, but
    this new token is not the ## operator."

    I don't really understand how or why the macro "hash_hash" works. I am guessing that the ## in the middle of "# ## #" is concatenating the two outer #s, but why that should work I can't really see. I don't seem to able to find anything in the standard that explains what is going on.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    because ## is a symbol used by the preprocessor, you can't use ## in a macro. So hash_hash is a way to produce ## without the preprocessor "noticing", (by concatenating # and #, using the ## symbol).

    It's cleverness that you probably never will need.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    I thought it probably was (cleverness you'll never need). I was looking for something else yesterday and came across it, and it has been doing my head in ever since.

    Anyway I still don't fully understand why it should work - from my understanding, the ## operator normally concatenates two arguments, yet surely the preceding and following #s aren't arguments?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by DL1 View Post
    I thought it probably was (cleverness you'll never need). I was looking for something else yesterday and came across it, and it has been doing my head in ever since.

    Anyway I still don't fully understand why it should work - from my understanding, the ## operator normally concatenates two arguments, yet surely the preceding and following #s aren't arguments?
    You can use it for anything there you want to "paste two bits of stuff together". We could do [I think the first will work, I know the second bit does]:
    Code:
    #define PI 3 ## .141592
    #define Symbol(x)  Prefix ## x ## PostFix
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by matsp View Post
    because ## is a symbol used by the preprocessor, you can't use ## in a macro. So hash_hash is a way to produce ## without the preprocessor "noticing", (by concatenating # and #, using the ## symbol).

    It's cleverness that you probably never will need.

    --
    Mats
    Actually, it's cleverness that I've needed only once so far in my career.
    I would have preferred to find a nice template solution, rather than resorting to macros, but once I worked out all the bugs in the macros, it saved a lot of time and code.
    If I remember correctly, the API I was using had a lot of Policy and Result classes with very similar names and identical usage; so I had a macro where I passed the unique part of the class name, and it then dynamically built the names of the Policy and Result classes using the ## pre-processor and did some stuff with them... It's kind of hard to explain in a paragraph, but it did help a LOT with maintainability (maybe not as much with readability), since I only needed to make a code change in one place instead of 10-15 places.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This is C programming though, so no templates and classes, but we still have the preprocessor
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    [code]
    #define PI 3 ## .141592
    #define Symbol(x) Prefix ## x ## PostFix
    [code]

    Of course. The penny is slowing beginning to drop...

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    This is C programming though, so no templates and classes, but we still have the preprocessor
    I know this is the C board, but ## is also in C++ and the only place I used it is in C++. The basic idea is pretty much the same, just replace classes with structs...

  9. #9
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Actually I think the cleverness that matsp was referring to was using macro concat to concat # and # to get around the fake that it treats ## as the concat token.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Here is a more complete example showing the use of ## (some of it creative!)
    Code:
    #include <stdio.h>
    
    #define FLOAT(x,y) x ## . ## y
    #define Symbol(x)  Prefix_ ## x ## _PostFix
    #define __SymbolName(x) #x
    #define _SymbolName(x) __SymbolName(x)
    #define SymbolName(x) _SymbolName(Symbol(x))
    
    #define PI FLOAT(3, 141592)
    
    int main()
    {
      char *Symbol(P) = SymbolName(P);
      printf("PI=%f, Symbol= %s\n", PI, Symbol(P));
      return 0;
    }
    It compiles and produces what I expected from the executable.

    Of course, it's all pretty meaningless.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Thantos View Post
    Actually I think the cleverness that matsp was referring to was using macro concat to concat # and # to get around the fake that it treats ## as the concat token.
    Yes. That is what I was referring to. Not being able to use ## in a macro is pretty rare, but there can conceivably be times when it's needed - I can't think of any such time, but I'm sure someone has had the need for it at some point in the past 20 or so years.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Thantos View Post
    Actually I think the cleverness that matsp was referring to was using macro concat to concat # and # to get around the fake that it treats ## as the concat token.
    Oh, I see now.
    Yeah, that's one thing I've never had to use.

  13. #13
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    The use of ##, from what I have read is a token paist operator, and can be used with variadic macros for c_99.

    From some obscure online document that I have saved when working with such preprocessor commands:

    " Second, the ## token paste operator has a special meaning when placed between a comma and a variable argument. If you write "

    Code:
    #define eprintf(format, …) fprintf (stderr, format, ##__VA_ARGS__)
    a google search may turn up more if you are interested in the use of variadic macros. I use them for debugging with the use printf().

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  2. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Operator Overloading (Bug, or error in code?)
    By QuietWhistler in forum C++ Programming
    Replies: 2
    Last Post: 01-25-2006, 08:38 AM
  5. operator overloading and dynamic memory program
    By jlmac2001 in forum C++ Programming
    Replies: 3
    Last Post: 04-06-2003, 11:51 PM