Implementing formatted print with the possibility to do nothing when it gets no arguments










4















I want to implement a macro named PRINT which gets zero or more parameters, and does the following:



  1. If it gets zero parameters - do nothing.

  2. If it gets one or more arguments - act like printf.

I succeed in implementing it as you can see in my code below, but only at the cost of calling to printf with an empty string in the case we get zero arguments.



Is there a way I can handle the zero arguments case without calling to printf (it's not efficient to print something when you just want to do nothing)?



#include <stdio.h>

#define PRINT(...) printf("" __VA_ARGS__);

int main()
PRINT();
PRINT("printn");
PRINT("print number: %dn", 7);
return 0;



output:



print
print number: 7









share|improve this question



















  • 2





    Where does the empty PRINT() come from? From another macro? (Any human programmer could probably just delete it.)

    – M Oehm
    Nov 14 '18 at 10:37











  • Jens Gustedt answered a question on detecting an empty argument list and showed how. It is quite involved.

    – Eric Postpischil
    Nov 15 '18 at 0:24
















4















I want to implement a macro named PRINT which gets zero or more parameters, and does the following:



  1. If it gets zero parameters - do nothing.

  2. If it gets one or more arguments - act like printf.

I succeed in implementing it as you can see in my code below, but only at the cost of calling to printf with an empty string in the case we get zero arguments.



Is there a way I can handle the zero arguments case without calling to printf (it's not efficient to print something when you just want to do nothing)?



#include <stdio.h>

#define PRINT(...) printf("" __VA_ARGS__);

int main()
PRINT();
PRINT("printn");
PRINT("print number: %dn", 7);
return 0;



output:



print
print number: 7









share|improve this question



















  • 2





    Where does the empty PRINT() come from? From another macro? (Any human programmer could probably just delete it.)

    – M Oehm
    Nov 14 '18 at 10:37











  • Jens Gustedt answered a question on detecting an empty argument list and showed how. It is quite involved.

    – Eric Postpischil
    Nov 15 '18 at 0:24














4












4








4








I want to implement a macro named PRINT which gets zero or more parameters, and does the following:



  1. If it gets zero parameters - do nothing.

  2. If it gets one or more arguments - act like printf.

I succeed in implementing it as you can see in my code below, but only at the cost of calling to printf with an empty string in the case we get zero arguments.



Is there a way I can handle the zero arguments case without calling to printf (it's not efficient to print something when you just want to do nothing)?



#include <stdio.h>

#define PRINT(...) printf("" __VA_ARGS__);

int main()
PRINT();
PRINT("printn");
PRINT("print number: %dn", 7);
return 0;



output:



print
print number: 7









share|improve this question
















I want to implement a macro named PRINT which gets zero or more parameters, and does the following:



  1. If it gets zero parameters - do nothing.

  2. If it gets one or more arguments - act like printf.

I succeed in implementing it as you can see in my code below, but only at the cost of calling to printf with an empty string in the case we get zero arguments.



Is there a way I can handle the zero arguments case without calling to printf (it's not efficient to print something when you just want to do nothing)?



#include <stdio.h>

#define PRINT(...) printf("" __VA_ARGS__);

int main()
PRINT();
PRINT("printn");
PRINT("print number: %dn", 7);
return 0;



output:



print
print number: 7






c macros printf variadic-functions






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 10:32









Jabberwocky

27.1k93772




27.1k93772










asked Nov 14 '18 at 10:12









RodrigoRodrigo

627




627







  • 2





    Where does the empty PRINT() come from? From another macro? (Any human programmer could probably just delete it.)

    – M Oehm
    Nov 14 '18 at 10:37











  • Jens Gustedt answered a question on detecting an empty argument list and showed how. It is quite involved.

    – Eric Postpischil
    Nov 15 '18 at 0:24













  • 2





    Where does the empty PRINT() come from? From another macro? (Any human programmer could probably just delete it.)

    – M Oehm
    Nov 14 '18 at 10:37











  • Jens Gustedt answered a question on detecting an empty argument list and showed how. It is quite involved.

    – Eric Postpischil
    Nov 15 '18 at 0:24








2




2





Where does the empty PRINT() come from? From another macro? (Any human programmer could probably just delete it.)

– M Oehm
Nov 14 '18 at 10:37





Where does the empty PRINT() come from? From another macro? (Any human programmer could probably just delete it.)

– M Oehm
Nov 14 '18 at 10:37













Jens Gustedt answered a question on detecting an empty argument list and showed how. It is quite involved.

– Eric Postpischil
Nov 15 '18 at 0:24






Jens Gustedt answered a question on detecting an empty argument list and showed how. It is quite involved.

– Eric Postpischil
Nov 15 '18 at 0:24













3 Answers
3






active

oldest

votes


















1














Both gcc and clang will completely eliminate the call to printf in the case that it is passed an empty format string. Probably that optimisation is reasonably common.



See here and here for disassembly on gcc.godbolt.org.



In short, don't worry about it.






share|improve this answer






























    1














    A solution is:



    #define Argument1(a,...) Argument2(a
    #define Argument2(a, b,...) b
    #define TestEmpty() ,
    #define PRINT(...) Argument1(TestEmpty __VA_ARGS__ (),), printf(__VA_ARGS__);,)


    For this source text:



    Test 0: PRINT()
    Test 1: PRINT("Hello, world.n")
    Test 2: PRINT("Result is %d.n", result)
    Test 3: PRINT("%d = %g.n", 3, 3.)


    the result of preprocessing is:



    Test 0:
    Test 1: printf("Hello, world.n");
    Test 2: printf("Result is %d.n", result);
    Test 3: printf("%d = %g.n", 3, 3.);


    This requires that the arguments to PRINT not start with a parenthesized item, which seems acceptable for this particular question. The code here is not a general solution for detecting an empty parameter when parentheses may be present.



    Explanation:



    • In preparing to replace PRINT, __VA_ARGS__ is replaced. TestEmpty is not replaced at this time because it is not followed by parentheses.

    • Then PRINT is replaced, and the result is rescanned.


    • Argument1 is identified for replacement. In preparation for that, its arguments are processed.

    • At this point, if __VA_ARGS__ is empty, we have have the tokens TestEmpty (), which are replaced by ,. Otherwise, TestEmpty <some tokens> () remains. Note that, if TestEmpty () is present, the , it expands to is the first argument to Argument1. It is not an argument separator, because the arguments to Argument1 have already been identified.

    • Then Argument1 is replaced, producing either Argument2(, (if __VA_ARGS was empty) or Argument2(TestEmpty possibly followed by additional tokens (otherwise).

    • The result is either Argument2(,, printf();,) or Argument2(TestEmpty <some tokens>, printf(<some tokens>);,), according to whether __VA_ARGS__ was empty or not.

    • The tokens are now rescanned for further replacement, so the , will now be recognized as an argument separator.

    • Finally, Argument2 is replaced with an empty token list or with printf(<some tokens>);.





    share|improve this answer

























    • Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

      – Andrew Henle
      Nov 15 '18 at 12:46











    • @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

      – Eric Postpischil
      Nov 15 '18 at 13:49












    • @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

      – Eric Postpischil
      Nov 15 '18 at 13:50



















    0














    If you do want to outsource the check of empty argument list to the macro, then perhaps something like this:



    #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

    #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)


    This relies on the compound literal getting size 1 in case of an empty string = null terminator only. Example:



    #include <stdio.h>

    #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

    #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

    int main (void)

    int i = 5;
    PRINT("%dn", i);
    PRINT();






    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%2f53297695%2fimplementing-formatted-print-with-the-possibility-to-do-nothing-when-it-gets-no%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      Both gcc and clang will completely eliminate the call to printf in the case that it is passed an empty format string. Probably that optimisation is reasonably common.



      See here and here for disassembly on gcc.godbolt.org.



      In short, don't worry about it.






      share|improve this answer



























        1














        Both gcc and clang will completely eliminate the call to printf in the case that it is passed an empty format string. Probably that optimisation is reasonably common.



        See here and here for disassembly on gcc.godbolt.org.



        In short, don't worry about it.






        share|improve this answer

























          1












          1








          1







          Both gcc and clang will completely eliminate the call to printf in the case that it is passed an empty format string. Probably that optimisation is reasonably common.



          See here and here for disassembly on gcc.godbolt.org.



          In short, don't worry about it.






          share|improve this answer













          Both gcc and clang will completely eliminate the call to printf in the case that it is passed an empty format string. Probably that optimisation is reasonably common.



          See here and here for disassembly on gcc.godbolt.org.



          In short, don't worry about it.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 14 '18 at 14:31









          ricirici

          154k19135202




          154k19135202























              1














              A solution is:



              #define Argument1(a,...) Argument2(a
              #define Argument2(a, b,...) b
              #define TestEmpty() ,
              #define PRINT(...) Argument1(TestEmpty __VA_ARGS__ (),), printf(__VA_ARGS__);,)


              For this source text:



              Test 0: PRINT()
              Test 1: PRINT("Hello, world.n")
              Test 2: PRINT("Result is %d.n", result)
              Test 3: PRINT("%d = %g.n", 3, 3.)


              the result of preprocessing is:



              Test 0:
              Test 1: printf("Hello, world.n");
              Test 2: printf("Result is %d.n", result);
              Test 3: printf("%d = %g.n", 3, 3.);


              This requires that the arguments to PRINT not start with a parenthesized item, which seems acceptable for this particular question. The code here is not a general solution for detecting an empty parameter when parentheses may be present.



              Explanation:



              • In preparing to replace PRINT, __VA_ARGS__ is replaced. TestEmpty is not replaced at this time because it is not followed by parentheses.

              • Then PRINT is replaced, and the result is rescanned.


              • Argument1 is identified for replacement. In preparation for that, its arguments are processed.

              • At this point, if __VA_ARGS__ is empty, we have have the tokens TestEmpty (), which are replaced by ,. Otherwise, TestEmpty <some tokens> () remains. Note that, if TestEmpty () is present, the , it expands to is the first argument to Argument1. It is not an argument separator, because the arguments to Argument1 have already been identified.

              • Then Argument1 is replaced, producing either Argument2(, (if __VA_ARGS was empty) or Argument2(TestEmpty possibly followed by additional tokens (otherwise).

              • The result is either Argument2(,, printf();,) or Argument2(TestEmpty <some tokens>, printf(<some tokens>);,), according to whether __VA_ARGS__ was empty or not.

              • The tokens are now rescanned for further replacement, so the , will now be recognized as an argument separator.

              • Finally, Argument2 is replaced with an empty token list or with printf(<some tokens>);.





              share|improve this answer

























              • Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

                – Andrew Henle
                Nov 15 '18 at 12:46











              • @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

                – Eric Postpischil
                Nov 15 '18 at 13:49












              • @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

                – Eric Postpischil
                Nov 15 '18 at 13:50
















              1














              A solution is:



              #define Argument1(a,...) Argument2(a
              #define Argument2(a, b,...) b
              #define TestEmpty() ,
              #define PRINT(...) Argument1(TestEmpty __VA_ARGS__ (),), printf(__VA_ARGS__);,)


              For this source text:



              Test 0: PRINT()
              Test 1: PRINT("Hello, world.n")
              Test 2: PRINT("Result is %d.n", result)
              Test 3: PRINT("%d = %g.n", 3, 3.)


              the result of preprocessing is:



              Test 0:
              Test 1: printf("Hello, world.n");
              Test 2: printf("Result is %d.n", result);
              Test 3: printf("%d = %g.n", 3, 3.);


              This requires that the arguments to PRINT not start with a parenthesized item, which seems acceptable for this particular question. The code here is not a general solution for detecting an empty parameter when parentheses may be present.



              Explanation:



              • In preparing to replace PRINT, __VA_ARGS__ is replaced. TestEmpty is not replaced at this time because it is not followed by parentheses.

              • Then PRINT is replaced, and the result is rescanned.


              • Argument1 is identified for replacement. In preparation for that, its arguments are processed.

              • At this point, if __VA_ARGS__ is empty, we have have the tokens TestEmpty (), which are replaced by ,. Otherwise, TestEmpty <some tokens> () remains. Note that, if TestEmpty () is present, the , it expands to is the first argument to Argument1. It is not an argument separator, because the arguments to Argument1 have already been identified.

              • Then Argument1 is replaced, producing either Argument2(, (if __VA_ARGS was empty) or Argument2(TestEmpty possibly followed by additional tokens (otherwise).

              • The result is either Argument2(,, printf();,) or Argument2(TestEmpty <some tokens>, printf(<some tokens>);,), according to whether __VA_ARGS__ was empty or not.

              • The tokens are now rescanned for further replacement, so the , will now be recognized as an argument separator.

              • Finally, Argument2 is replaced with an empty token list or with printf(<some tokens>);.





              share|improve this answer

























              • Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

                – Andrew Henle
                Nov 15 '18 at 12:46











              • @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

                – Eric Postpischil
                Nov 15 '18 at 13:49












              • @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

                – Eric Postpischil
                Nov 15 '18 at 13:50














              1












              1








              1







              A solution is:



              #define Argument1(a,...) Argument2(a
              #define Argument2(a, b,...) b
              #define TestEmpty() ,
              #define PRINT(...) Argument1(TestEmpty __VA_ARGS__ (),), printf(__VA_ARGS__);,)


              For this source text:



              Test 0: PRINT()
              Test 1: PRINT("Hello, world.n")
              Test 2: PRINT("Result is %d.n", result)
              Test 3: PRINT("%d = %g.n", 3, 3.)


              the result of preprocessing is:



              Test 0:
              Test 1: printf("Hello, world.n");
              Test 2: printf("Result is %d.n", result);
              Test 3: printf("%d = %g.n", 3, 3.);


              This requires that the arguments to PRINT not start with a parenthesized item, which seems acceptable for this particular question. The code here is not a general solution for detecting an empty parameter when parentheses may be present.



              Explanation:



              • In preparing to replace PRINT, __VA_ARGS__ is replaced. TestEmpty is not replaced at this time because it is not followed by parentheses.

              • Then PRINT is replaced, and the result is rescanned.


              • Argument1 is identified for replacement. In preparation for that, its arguments are processed.

              • At this point, if __VA_ARGS__ is empty, we have have the tokens TestEmpty (), which are replaced by ,. Otherwise, TestEmpty <some tokens> () remains. Note that, if TestEmpty () is present, the , it expands to is the first argument to Argument1. It is not an argument separator, because the arguments to Argument1 have already been identified.

              • Then Argument1 is replaced, producing either Argument2(, (if __VA_ARGS was empty) or Argument2(TestEmpty possibly followed by additional tokens (otherwise).

              • The result is either Argument2(,, printf();,) or Argument2(TestEmpty <some tokens>, printf(<some tokens>);,), according to whether __VA_ARGS__ was empty or not.

              • The tokens are now rescanned for further replacement, so the , will now be recognized as an argument separator.

              • Finally, Argument2 is replaced with an empty token list or with printf(<some tokens>);.





              share|improve this answer















              A solution is:



              #define Argument1(a,...) Argument2(a
              #define Argument2(a, b,...) b
              #define TestEmpty() ,
              #define PRINT(...) Argument1(TestEmpty __VA_ARGS__ (),), printf(__VA_ARGS__);,)


              For this source text:



              Test 0: PRINT()
              Test 1: PRINT("Hello, world.n")
              Test 2: PRINT("Result is %d.n", result)
              Test 3: PRINT("%d = %g.n", 3, 3.)


              the result of preprocessing is:



              Test 0:
              Test 1: printf("Hello, world.n");
              Test 2: printf("Result is %d.n", result);
              Test 3: printf("%d = %g.n", 3, 3.);


              This requires that the arguments to PRINT not start with a parenthesized item, which seems acceptable for this particular question. The code here is not a general solution for detecting an empty parameter when parentheses may be present.



              Explanation:



              • In preparing to replace PRINT, __VA_ARGS__ is replaced. TestEmpty is not replaced at this time because it is not followed by parentheses.

              • Then PRINT is replaced, and the result is rescanned.


              • Argument1 is identified for replacement. In preparation for that, its arguments are processed.

              • At this point, if __VA_ARGS__ is empty, we have have the tokens TestEmpty (), which are replaced by ,. Otherwise, TestEmpty <some tokens> () remains. Note that, if TestEmpty () is present, the , it expands to is the first argument to Argument1. It is not an argument separator, because the arguments to Argument1 have already been identified.

              • Then Argument1 is replaced, producing either Argument2(, (if __VA_ARGS was empty) or Argument2(TestEmpty possibly followed by additional tokens (otherwise).

              • The result is either Argument2(,, printf();,) or Argument2(TestEmpty <some tokens>, printf(<some tokens>);,), according to whether __VA_ARGS__ was empty or not.

              • The tokens are now rescanned for further replacement, so the , will now be recognized as an argument separator.

              • Finally, Argument2 is replaced with an empty token list or with printf(<some tokens>);.






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 15 '18 at 18:17

























              answered Nov 15 '18 at 3:35









              Eric PostpischilEric Postpischil

              75.4k880162




              75.4k880162












              • Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

                – Andrew Henle
                Nov 15 '18 at 12:46











              • @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

                – Eric Postpischil
                Nov 15 '18 at 13:49












              • @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

                – Eric Postpischil
                Nov 15 '18 at 13:50


















              • Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

                – Andrew Henle
                Nov 15 '18 at 12:46











              • @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

                – Eric Postpischil
                Nov 15 '18 at 13:49












              • @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

                – Eric Postpischil
                Nov 15 '18 at 13:50

















              Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

              – Andrew Henle
              Nov 15 '18 at 12:46





              Brilliant use of the preprocessor. But what about Test 4? char *str = "This is a string.n"; PRINT(str); Or Test 5? char *str = ""; PRINT(str); I'd also be very concerned about maintainability and loathe to release those macros in the wilds of some large project.

              – Andrew Henle
              Nov 15 '18 at 12:46













              @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

              – Eric Postpischil
              Nov 15 '18 at 13:49






              @AndrewHenle: Your proposed tests 4 and 5 result in printf(str);, as desired. As long as the first argument does not start with a parentheses, I think the macros will work. If they start with any non-empty parentheses, an error should be generated, so the problem will be caught. It is rare for printf arguments to start with parentheses. I suspect the most likely case would be something like PRINT(SomeMacroToPrepareFormatString(stuff),…), where the macro expands to a parenthesized sequence (out of the common habit of parenthesizing macro replacement text, not necessary in this case…

              – Eric Postpischil
              Nov 15 '18 at 13:49














              @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

              – Eric Postpischil
              Nov 15 '18 at 13:50






              @AndrewHenle: … unless the replacement text contains a comma operator that needs to be parenthesized to prevent it from being interpreted as an argument separator). I would not recommend this for a large project; I am just answering the Stack Overflow question because knowledge is valuable.

              – Eric Postpischil
              Nov 15 '18 at 13:50












              0














              If you do want to outsource the check of empty argument list to the macro, then perhaps something like this:



              #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

              #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)


              This relies on the compound literal getting size 1 in case of an empty string = null terminator only. Example:



              #include <stdio.h>

              #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

              #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

              int main (void)

              int i = 5;
              PRINT("%dn", i);
              PRINT();






              share|improve this answer



























                0














                If you do want to outsource the check of empty argument list to the macro, then perhaps something like this:



                #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

                #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)


                This relies on the compound literal getting size 1 in case of an empty string = null terminator only. Example:



                #include <stdio.h>

                #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

                #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

                int main (void)

                int i = 5;
                PRINT("%dn", i);
                PRINT();






                share|improve this answer

























                  0












                  0








                  0







                  If you do want to outsource the check of empty argument list to the macro, then perhaps something like this:



                  #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

                  #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)


                  This relies on the compound literal getting size 1 in case of an empty string = null terminator only. Example:



                  #include <stdio.h>

                  #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

                  #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

                  int main (void)

                  int i = 5;
                  PRINT("%dn", i);
                  PRINT();






                  share|improve this answer













                  If you do want to outsource the check of empty argument list to the macro, then perhaps something like this:



                  #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

                  #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)


                  This relies on the compound literal getting size 1 in case of an empty string = null terminator only. Example:



                  #include <stdio.h>

                  #define HAS_ARGS(...) (sizeof( (char)#__VA_ARGS__ ) > 1)

                  #define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

                  int main (void)

                  int i = 5;
                  PRINT("%dn", i);
                  PRINT();







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 14 '18 at 14:45









                  LundinLundin

                  109k17160265




                  109k17160265



























                      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.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297695%2fimplementing-formatted-print-with-the-possibility-to-do-nothing-when-it-gets-no%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







                      這個網誌中的熱門文章

                      How to read a connectionString WITH PROVIDER in .NET Core?

                      Node.js Script on GitHub Pages or Amazon S3

                      Museum of Modern and Contemporary Art of Trento and Rovereto