preprocessor q: impossible macro?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Eric

    #1

    preprocessor q: impossible macro?

    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:
    .....somefuncti on("#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:
    .....somefuncti on(MYMACRO(IDB_ BUTTON))....

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

    Is this possible at all?
    Eric


  • Victor Bazarov

    #2
    Re: preprocessor q: impossible macro?

    Eric wrote:[color=blue]
    > 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:
    > ....somefunctio n("#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:
    > ....somefunctio n(MYMACRO(IDB_B UTTON))....
    >
    > I didn't get such a macro to work. I tried:
    > #define MYMACRO(num) "#" #num
    > but this only yields to
    > ....somefunctio n("#" "IDB_BUTTON").. ..
    > I also tried with the token-pasting operator (##) etc.
    >
    > Is this possible at all?[/color]

    Yes, you need an indirect "stringizin g" 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_BUT TON));
    }

    V

    Comment

    • Charles Mills

      #3
      Re: preprocessor q: impossible macro?

      Victor Bazarov wrote:[color=blue]
      > Eric wrote:[color=green]
      > > 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:
      > > ....somefunctio n("#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:
      > > ....somefunctio n(MYMACRO(IDB_B UTTON))....
      > >
      > > I didn't get such a macro to work. I tried:
      > > #define MYMACRO(num) "#" #num
      > > but this only yields to
      > > ....somefunctio n("#" "IDB_BUTTON").. ..
      > > I also tried with the token-pasting operator (##) etc.
      > >
      > > Is this possible at all?[/color]
      >
      > Yes, you need an indirect "stringizin g" 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_BUT TON));
      > }
      >
      > V[/color]

      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_BUT TON));
      }

      -Charlie

      Comment

      • Victor Bazarov

        #4
        Re: preprocessor q: impossible macro?

        Charles Mills wrote:[color=blue]
        > Victor Bazarov wrote:
        > [..][color=green]
        >>
        >> #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_BUT TON));
        >> }
        >>
        >>V[/color]
        >
        >
        > The above solution does not compile. [..][/color]

        On what compiler? What is the error message?

        V

        Comment

        • Charles Mills

          #5
          Re: preprocessor q: impossible macro?



          Victor Bazarov wrote:[color=blue]
          > Charles Mills wrote:[color=green]
          > > Victor Bazarov wrote:
          > > [..][color=darkred]
          > >>
          > >> #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_BUT TON));
          > >> }
          > >>
          > >>V[/color]
          > >
          > >
          > > The above solution does not compile. [..][/color]
          >
          > On what compiler? What is the error message?
          >
          > V[/color]

          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

          Comment

          • Victor Bazarov

            #6
            Re: preprocessor q: impossible macro?

            Charles Mills wrote:[color=blue]
            > Victor Bazarov wrote:
            >[color=green]
            >>Charles Mills wrote:
            >>[color=darkred]
            >>>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_BUT TON));
            >>>> }
            >>>>
            >>>>V
            >>>
            >>>
            >>>The above solution does not compile. [..][/color]
            >>
            >>On what compiler? What is the error message?
            >>
            >>V[/color]
            >
            >
            > gcc
            > pasting ""#"" and "STR" does not give a valid preprocessing token
            >
            > The standard says that token pasting must result in a valid C token.[/color]

            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_BU TTON)' 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

            Comment

            • Rob Williscroft

              #7
              Re: preprocessor q: impossible macro?

              Victor Bazarov wrote in news:ASSCe.1945 6$Tf5.2888
              @newsread1.mlps ca01.us.to.veri o.net in comp.lang.c++:
              [color=blue]
              >
              > Yes, you need an indirect "stringizin g" macro for that.
              >
              > #define STR(x) #x
              > #define MYMACRO(num) "#" ## STR(num)
              >[/color]

              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.
              [color=blue]
              > #define IDB_BUTTON 225
              >
              > #include <stdio.h>
              >
              > int main(void) {
              > printf("Got %s\n", MYMACRO(IDB_BUT TON));
              > }[/color]

              Rob.
              --

              Comment

              • Victor Bazarov

                #8
                Re: preprocessor q: impossible macro?

                Rob Williscroft wrote:[color=blue]
                > Victor Bazarov wrote in news:ASSCe.1945 6$Tf5.2888
                > @newsread1.mlps ca01.us.to.veri o.net in comp.lang.c++:
                >
                >[color=green]
                >>Yes, you need an indirect "stringizin g" macro for that.
                >>
                >> #define STR(x) #x
                >> #define MYMACRO(num) "#" ## STR(num)
                >>[/color]
                >
                >
                > 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.[/color]

                I don't understand this sentence. Perhaps you could rephrase...
                Also, see my reply to Charles Mills. The code is valid.
                [color=blue][color=green]
                >> #define IDB_BUTTON 225
                >>
                >> #include <stdio.h>
                >>
                >> int main(void) {
                >> printf("Got %s\n", MYMACRO(IDB_BUT TON));
                >> }[/color]
                >
                >
                > Rob.[/color]

                V

                Comment

                • Me

                  #9
                  Re: preprocessor q: impossible macro?

                  Eric wrote:[color=blue]
                  > 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:
                  > ....somefunctio n("#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:
                  > ....somefunctio n(MYMACRO(IDB_B UTTON))....
                  >
                  > I didn't get such a macro to work. I tried:
                  > #define MYMACRO(num) "#" #num
                  > but this only yields to
                  > ....somefunctio n("#" "IDB_BUTTON").. ..
                  > I also tried with the token-pasting operator (##) etc.
                  >
                  > Is this possible at all?[/color]

                  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.

                  Comment

                  • Rob Williscroft

                    #10
                    Re: preprocessor q: impossible macro?

                    Victor Bazarov wrote in news:JoUCe.1946 3$Tf5.10002
                    @newsread1.mlps ca01.us.to.veri o.net in comp.lang.c++:
                    [color=blue][color=green][color=darkred]
                    >>> #define MYMACRO(num) "#" ## STR(num)
                    >>>[/color]
                    >>
                    >>
                    >> 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.[/color]
                    >
                    > I don't understand this sentence. Perhaps you could rephrase...[/color]

                    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.
                    [color=blue]
                    > Also, see my reply to Charles Mills. The code is valid.
                    >[/color]

                    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.
                    --

                    Comment

                    • Victor Bazarov

                      #11
                      Re: preprocessor q: impossible macro?

                      Rob Williscroft wrote:[color=blue]
                      > Victor Bazarov wrote in news:JoUCe.1946 3$Tf5.10002
                      > @newsread1.mlps ca01.us.to.veri o.net in comp.lang.c++:
                      >
                      >[color=green][color=darkred]
                      >>>> #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.[/color]
                      >>
                      >>I don't understand this sentence. Perhaps you could rephrase...[/color]
                      >
                      >
                      > 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.
                      >
                      >[color=green]
                      >>Also, see my reply to Charles Mills. The code is valid.
                      >>[/color]
                      >
                      >
                      > 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[/color]

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

                      V

                      Comment

                      • Rob Williscroft

                        #12
                        Re: preprocessor q: impossible macro?

                        Victor Bazarov wrote in news:q%UCe.1946 6$Tf5.9220
                        @newsread1.mlps ca01.us.to.veri o.net in comp.lang.c++:
                        [color=blue][color=green]
                        >> 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[/color]
                        >
                        > Yes, how is that applicable here? Did you read my reply to Charles?
                        >
                        >[/color]

                        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.
                        --

                        Comment

                        • Charles Mills

                          #13
                          Re: preprocessor q: impossible macro?

                          Rob Williscroft wrote:[color=blue]
                          > Victor Bazarov wrote in news:q%UCe.1946 6$Tf5.9220
                          > @newsread1.mlps ca01.us.to.veri o.net in comp.lang.c++:
                          >[color=green][color=darkred]
                          > >> 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[/color]
                          > >
                          > > Yes, how is that applicable here? Did you read my reply to Charles?
                          > >
                          > >[/color]
                          >
                          > 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.
                          > --
                          > http://www.victim-prime.dsl.pipex.com/[/color]

                          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

                          Comment

                          • Rob Williscroft

                            #14
                            Re: preprocessor q: impossible macro?

                            Charles Mills wrote in news:1121724926 .368427.251760
                            @g49g2000cwa.go oglegroups.com in comp.lang.c++:
                            [color=blue]
                            >
                            > I think you mean a string literal is a single token, right?[/color]

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

                            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.
                            [color=blue]
                            > Another example would be pasting the tokens c and ++
                            > c ## ++
                            > creates the token
                            > c++
                            > which is not a valid C token :)
                            >[/color]

                            Agreed.

                            Rob.
                            --

                            Comment

                            • Greg

                              #15
                              Re: preprocessor q: impossible macro?



                              Victor Bazarov wrote:[color=blue]
                              > Charles Mills wrote:[color=green]
                              > > Victor Bazarov wrote:
                              > >[color=darkred]
                              > >>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_BUT TON));
                              > >>>> }
                              > >>>>
                              > >>>>V
                              > >>>
                              > >>>
                              > >>>The above solution does not compile. [..]
                              > >>
                              > >>On what compiler? What is the error message?
                              > >>
                              > >>V[/color][/color]
                              >
                              > IOW, the result of 'MYMACRO(IDB_BU TTON)' 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[/color]

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

                              std::printf("Go t %s\n", "#""IDB_BUT TON" );

                              whereas the corrrect result would be:

                              std::printf("Go t %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("Go t %s\n", "#" "225" );

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

                              Greg

                              Comment

                              Working...