Standard Behavior Of Function-Like Macro With Empty Argument Next To ## Operator?











up vote
5
down vote

favorite












Take the following example:



#define FOO(x) bar x ## baz
FOO( )


What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?



I ran the above through gcc -E and clang -E, and both produced output equivalent to the following:



bar baz




Also, if the above preprocessed output is considered to conform to the standards, then what about this?



#define FOO(x) x ## baz
FOO( )


With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror flags):



baz




The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:




6.8.3.3 The ## operator



A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.



If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.




Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz.





Furthermore, the standard states:




For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.




So, considering the first example I gave above, why shouldn't the correct output be, say, this?



barbaz





UPDATE



As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:



gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -


The output (with error) is:



foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"

bar baz
cc1: all warnings being treated as errors


The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.



Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.










share|improve this question
























  • If you want to achieve barbaz you need two token-pasting operators: #define FOO(x) bar ## x ## baz. This works with FOO(X) as well as with FOO(). (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -, although I was actually sure about this.) ;-)
    – Scheff
    Nov 20 at 6:33












  • @4386427 Sorry, that's a typo in my question. I meant to write baz. Fixing that now.
    – jinscoe123
    Nov 20 at 6:36










  • @Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
    – jinscoe123
    Nov 20 at 6:39










  • OK. As I understand token-pasting, with #define FOO(x) bar x ## baz and FOO(X) the expected is bar Xbaz, and for FOO() the expected is bar baz. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
    – Scheff
    Nov 20 at 6:42












  • I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
    – Scheff
    Nov 20 at 6:50

















up vote
5
down vote

favorite












Take the following example:



#define FOO(x) bar x ## baz
FOO( )


What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?



I ran the above through gcc -E and clang -E, and both produced output equivalent to the following:



bar baz




Also, if the above preprocessed output is considered to conform to the standards, then what about this?



#define FOO(x) x ## baz
FOO( )


With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror flags):



baz




The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:




6.8.3.3 The ## operator



A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.



If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.




Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz.





Furthermore, the standard states:




For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.




So, considering the first example I gave above, why shouldn't the correct output be, say, this?



barbaz





UPDATE



As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:



gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -


The output (with error) is:



foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"

bar baz
cc1: all warnings being treated as errors


The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.



Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.










share|improve this question
























  • If you want to achieve barbaz you need two token-pasting operators: #define FOO(x) bar ## x ## baz. This works with FOO(X) as well as with FOO(). (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -, although I was actually sure about this.) ;-)
    – Scheff
    Nov 20 at 6:33












  • @4386427 Sorry, that's a typo in my question. I meant to write baz. Fixing that now.
    – jinscoe123
    Nov 20 at 6:36










  • @Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
    – jinscoe123
    Nov 20 at 6:39










  • OK. As I understand token-pasting, with #define FOO(x) bar x ## baz and FOO(X) the expected is bar Xbaz, and for FOO() the expected is bar baz. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
    – Scheff
    Nov 20 at 6:42












  • I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
    – Scheff
    Nov 20 at 6:50















up vote
5
down vote

favorite









up vote
5
down vote

favorite











Take the following example:



#define FOO(x) bar x ## baz
FOO( )


What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?



I ran the above through gcc -E and clang -E, and both produced output equivalent to the following:



bar baz




Also, if the above preprocessed output is considered to conform to the standards, then what about this?



#define FOO(x) x ## baz
FOO( )


With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror flags):



baz




The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:




6.8.3.3 The ## operator



A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.



If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.




Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz.





Furthermore, the standard states:




For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.




So, considering the first example I gave above, why shouldn't the correct output be, say, this?



barbaz





UPDATE



As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:



gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -


The output (with error) is:



foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"

bar baz
cc1: all warnings being treated as errors


The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.



Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.










share|improve this question















Take the following example:



#define FOO(x) bar x ## baz
FOO( )


What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?



I ran the above through gcc -E and clang -E, and both produced output equivalent to the following:



bar baz




Also, if the above preprocessed output is considered to conform to the standards, then what about this?



#define FOO(x) x ## baz
FOO( )


With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror flags):



baz




The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:




6.8.3.3 The ## operator



A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.



If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.




Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz.





Furthermore, the standard states:




For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.




So, considering the first example I gave above, why shouldn't the correct output be, say, this?



barbaz





UPDATE



As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:



gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -


The output (with error) is:



foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"

bar baz
cc1: all warnings being treated as errors


The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.



Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.







c c-preprocessor preprocessor






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 8:02

























asked Nov 20 at 6:17









jinscoe123

16412




16412












  • If you want to achieve barbaz you need two token-pasting operators: #define FOO(x) bar ## x ## baz. This works with FOO(X) as well as with FOO(). (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -, although I was actually sure about this.) ;-)
    – Scheff
    Nov 20 at 6:33












  • @4386427 Sorry, that's a typo in my question. I meant to write baz. Fixing that now.
    – jinscoe123
    Nov 20 at 6:36










  • @Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
    – jinscoe123
    Nov 20 at 6:39










  • OK. As I understand token-pasting, with #define FOO(x) bar x ## baz and FOO(X) the expected is bar Xbaz, and for FOO() the expected is bar baz. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
    – Scheff
    Nov 20 at 6:42












  • I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
    – Scheff
    Nov 20 at 6:50




















  • If you want to achieve barbaz you need two token-pasting operators: #define FOO(x) bar ## x ## baz. This works with FOO(X) as well as with FOO(). (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -, although I was actually sure about this.) ;-)
    – Scheff
    Nov 20 at 6:33












  • @4386427 Sorry, that's a typo in my question. I meant to write baz. Fixing that now.
    – jinscoe123
    Nov 20 at 6:36










  • @Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
    – jinscoe123
    Nov 20 at 6:39










  • OK. As I understand token-pasting, with #define FOO(x) bar x ## baz and FOO(X) the expected is bar Xbaz, and for FOO() the expected is bar baz. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
    – Scheff
    Nov 20 at 6:42












  • I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
    – Scheff
    Nov 20 at 6:50


















If you want to achieve barbaz you need two token-pasting operators: #define FOO(x) bar ## x ## baz. This works with FOO(X) as well as with FOO(). (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -, although I was actually sure about this.) ;-)
– Scheff
Nov 20 at 6:33






If you want to achieve barbaz you need two token-pasting operators: #define FOO(x) bar ## x ## baz. This works with FOO(X) as well as with FOO(). (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -, although I was actually sure about this.) ;-)
– Scheff
Nov 20 at 6:33














@4386427 Sorry, that's a typo in my question. I meant to write baz. Fixing that now.
– jinscoe123
Nov 20 at 6:36




@4386427 Sorry, that's a typo in my question. I meant to write baz. Fixing that now.
– jinscoe123
Nov 20 at 6:36












@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 at 6:39




@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 at 6:39












OK. As I understand token-pasting, with #define FOO(x) bar x ## baz and FOO(X) the expected is bar Xbaz, and for FOO() the expected is bar baz. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
– Scheff
Nov 20 at 6:42






OK. As I understand token-pasting, with #define FOO(x) bar x ## baz and FOO(X) the expected is bar Xbaz, and for FOO() the expected is bar baz. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
– Scheff
Nov 20 at 6:42














I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 at 6:50






I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 at 6:50














2 Answers
2






active

oldest

votes

















up vote
5
down vote



accepted










Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,


The word "technically" here is redundant. The replacement list of both of your macros has x before the ##, so that rule doesn't apply.



but x does expand to... a single space? nothing?


6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.



So your whitespace in your argument to FOO is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:



6.10.3.3 p2:



however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.


The next paragraph, 3, applies to the result here:



concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.


So, placemarker pasted onto baz produces baz.






share|improve this answer




























    up vote
    0
    down vote













    If you have this:



    #define FOO(x) bar x ## baz                
    FOO();


    You get bar baz. So the space in the FOO call is not relevant.



    If you have this:



    #define FOO(x) bar ## x ## baz                 
    FOO();


    you get barbaz because you ask to get all those pasted together.



    But you write:



    #define FOO(x) bar x ## baz                 
    FOO();


    You get bar baz because you ask for bar and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz that gives you bar,baz.






    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387287%2fstandard-behavior-of-function-like-macro-with-empty-argument-next-to-operator%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      5
      down vote



      accepted










      Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,


      The word "technically" here is redundant. The replacement list of both of your macros has x before the ##, so that rule doesn't apply.



      but x does expand to... a single space? nothing?


      6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.



      So your whitespace in your argument to FOO is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:



      6.10.3.3 p2:



      however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.


      The next paragraph, 3, applies to the result here:



      concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.


      So, placemarker pasted onto baz produces baz.






      share|improve this answer

























        up vote
        5
        down vote



        accepted










        Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,


        The word "technically" here is redundant. The replacement list of both of your macros has x before the ##, so that rule doesn't apply.



        but x does expand to... a single space? nothing?


        6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.



        So your whitespace in your argument to FOO is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:



        6.10.3.3 p2:



        however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.


        The next paragraph, 3, applies to the result here:



        concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.


        So, placemarker pasted onto baz produces baz.






        share|improve this answer























          up vote
          5
          down vote



          accepted







          up vote
          5
          down vote



          accepted






          Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,


          The word "technically" here is redundant. The replacement list of both of your macros has x before the ##, so that rule doesn't apply.



          but x does expand to... a single space? nothing?


          6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.



          So your whitespace in your argument to FOO is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:



          6.10.3.3 p2:



          however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.


          The next paragraph, 3, applies to the result here:



          concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.


          So, placemarker pasted onto baz produces baz.






          share|improve this answer












          Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,


          The word "technically" here is redundant. The replacement list of both of your macros has x before the ##, so that rule doesn't apply.



          but x does expand to... a single space? nothing?


          6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.



          So your whitespace in your argument to FOO is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:



          6.10.3.3 p2:



          however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.


          The next paragraph, 3, applies to the result here:



          concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.


          So, placemarker pasted onto baz produces baz.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 20 at 7:15









          H Walters

          1,671159




          1,671159
























              up vote
              0
              down vote













              If you have this:



              #define FOO(x) bar x ## baz                
              FOO();


              You get bar baz. So the space in the FOO call is not relevant.



              If you have this:



              #define FOO(x) bar ## x ## baz                 
              FOO();


              you get barbaz because you ask to get all those pasted together.



              But you write:



              #define FOO(x) bar x ## baz                 
              FOO();


              You get bar baz because you ask for bar and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz that gives you bar,baz.






              share|improve this answer

























                up vote
                0
                down vote













                If you have this:



                #define FOO(x) bar x ## baz                
                FOO();


                You get bar baz. So the space in the FOO call is not relevant.



                If you have this:



                #define FOO(x) bar ## x ## baz                 
                FOO();


                you get barbaz because you ask to get all those pasted together.



                But you write:



                #define FOO(x) bar x ## baz                 
                FOO();


                You get bar baz because you ask for bar and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz that gives you bar,baz.






                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  If you have this:



                  #define FOO(x) bar x ## baz                
                  FOO();


                  You get bar baz. So the space in the FOO call is not relevant.



                  If you have this:



                  #define FOO(x) bar ## x ## baz                 
                  FOO();


                  you get barbaz because you ask to get all those pasted together.



                  But you write:



                  #define FOO(x) bar x ## baz                 
                  FOO();


                  You get bar baz because you ask for bar and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz that gives you bar,baz.






                  share|improve this answer












                  If you have this:



                  #define FOO(x) bar x ## baz                
                  FOO();


                  You get bar baz. So the space in the FOO call is not relevant.



                  If you have this:



                  #define FOO(x) bar ## x ## baz                 
                  FOO();


                  you get barbaz because you ask to get all those pasted together.



                  But you write:



                  #define FOO(x) bar x ## baz                 
                  FOO();


                  You get bar baz because you ask for bar and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz that gives you bar,baz.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 20 at 7:00









                  perreal

                  71.7k9110138




                  71.7k9110138






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387287%2fstandard-behavior-of-function-like-macro-with-empty-argument-next-to-operator%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Costa Masnaga

                      Fotorealismo

                      Sidney Franklin