Standard alternative to GCC's ##__VA_ARGS__ trick?

update-alternatives: error: no alternatives for gcc
centos gcc alternatives
update-alternatives gcc 8
ubuntu 16.04 default gcc version
update-alternatives gcc-6
gcc versions
gcc 9
install gcc ubuntu

There is a well-known problem with empty args for variadic macros in C99.

example:

#define FOO(...)       printf(__VA_ARGS__)
#define BAR(fmt, ...)  printf(fmt, __VA_ARGS__)

FOO("this works fine");
BAR("this breaks!");

The use of BAR() above is indeed incorrect according to the C99 standard, since it will expand to:

printf("this breaks!",);

Note the trailing comma - not workable.

Some compilers (eg: Visual Studio 2010) will quietly get rid of that trailing comma for you. Other compilers (eg: GCC) support putting ## in front of __VA_ARGS__, like so:

#define BAR(fmt, ...)  printf(fmt, ##__VA_ARGS__)

But is there a standards-compliant way to get this behavior? Perhaps using multiple macros?

Right now, the ## version seems fairly well-supported (at least on my platforms), but I'd really rather use a standards-compliant solution.

Pre-emptive: I know I could just write a small function. I'm trying to do this using macros.

Edit: Here is an example (though simple) of why I would want to use BAR():

#define BAR(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)

BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);

This automatically adds a newline to my BAR() logging statements, assuming fmt is always a double-quoted C-string. It does NOT print the newline as a separate printf(), which is advantageous if the logging is line-buffered and coming from multiple sources asynchronously.

It is possible to avoid the use of GCC's ,##__VA_ARGS__ extension if you are willing to accept some hardcoded upper limit on the number of arguments you can pass to your variadic macro, as described in Richard Hansen's answer to this question. If you do not want to have any such limit, however, to the best of my knowledge it is not possible using only C99-specified preprocessor features; you must use some extension to the language. clang and icc have adopted this GCC extension, but MSVC has not.

Back in 2001 I wrote up the GCC extension for standardization (and the related extension that lets you use a name other than __VA_ARGS__ for the rest-parameter) in document N976, but that received no response whatsoever from the committee; I don't even know if anyone read it. In 2016 it was proposed again in N2023, and I encourage anyone who knows how that proposal is going to let us know in the comments.

How to change the default GCC compiler in Ubuntu?, As @Tommy suggested, you should use update-alternatives . It assigns values to every software of a family, so that it defines the order in which the applications  Until Microsoft announces a GCC launch date and it becomes available in your tenant, let’s talk about your Private Channel Alternatives for Office 365 Users in the Public Sector. Before we discuss alternatives to Private Channels, it’s important to keep in mind why they’ve become such a widely requested feature in the first place.

How to choose the default gcc and g++ version?, First erase the current update-alternatives setup for gcc and g++ : sudo update-​alternatives --remove-all gcc sudo update-alternatives  The compatibility and preview gcc packages provide the compiler binaries under a name that incorporates the version number. For instance, to compile code on Red Hat Enterprise Linux 5.4 using the gcc 4.4 Technology Preview packages, call the compiler as gcc44. When building code that uses a "configure" script, this is best done at configure time:

Not a general solution, but in the case of printf you could append a newline like:

#define BAR_HELPER(fmt, ...) printf(fmt "\n%s", __VA_ARGS__)
#define BAR(...) BAR_HELPER(__VA_ARGS__, "")

I believe it ignores any extra args that aren't referenced in the format string. So you could probably even get away with:

#define BAR_HELPER(fmt, ...) printf(fmt "\n", __VA_ARGS__)
#define BAR(...) BAR_HELPER(__VA_ARGS__, 0)

I can't believe C99 was approved without a standard way to do this. AFAICT the problem exists in C++11 too.

GCC, Clang, and MSVC compilers with C++, This article looks at support for C++ standards in three popular compiler alternatives: GCC: The GNU Compiler Collection (GCC) [1] is the quintessential free  Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more Standard alternative to GCC's ##__VA_ARGS__ trick?

There is a way to handle this specific case using something like Boost.Preprocessor. You can use BOOST_PP_VARIADIC_SIZE to check the size of the argument list, and then conditionaly expand to another macro. The one shortcoming of this is that it can't distinguish between 0 and 1 argument, and the reason for this becomes clear once you consider the following:

BOOST_PP_VARIADIC_SIZE()      // expands to 1
BOOST_PP_VARIADIC_SIZE(,)     // expands to 2
BOOST_PP_VARIADIC_SIZE(,,)    // expands to 3
BOOST_PP_VARIADIC_SIZE(a)     // expands to 1
BOOST_PP_VARIADIC_SIZE(a,)    // expands to 2
BOOST_PP_VARIADIC_SIZE(,b)    // expands to 2
BOOST_PP_VARIADIC_SIZE(a,b)   // expands to 2
BOOST_PP_VARIADIC_SIZE(a, ,c) // expands to 3

The empty macro argument list actually consists of one argument that happens to be empty.

In this case, we are lucky since your desired macro always has at least 1 argument, we can implement it as two "overload" macros:

#define BAR_0(fmt) printf(fmt "\n")
#define BAR_1(fmt, ...) printf(fmt "\n", __VA_ARGS__)

And then another macro to switch between them, such as:

#define BAR(...) \
    BOOST_PP_CAT(BAR_, BOOST_PP_GREATER(
        BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1))(__VA_ARGS__) \
    /**/

or

#define BAR(...) BOOST_PP_IIF( \
    BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1), \
        BAR_1, BAR_0)(__VA_ARGS__) \
    /**/

Whichever you find more readable (I prefer the first as it gives you a general form for overloading macros on the number of arguments).

It is also possible to do this with a single macro by accessing and mutating the variable arguments list, but it is way less readable, and is very specific to this problem:

#define BAR(...) printf( \
    BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__) "\n" \
    BOOST_PP_COMMA_IF( \
        BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1)) \
    BOOST_PP_ARRAY_ENUM(BOOST_PP_ARRAY_POP_FRONT( \
        BOOST_PP_VARIADIC_TO_ARRAY(__VA_ARGS__)))) \
    /**/

Also, why is there no BOOST_PP_ARRAY_ENUM_TRAILING? It would make this solution much less horrible.

Edit: Alright, here is a BOOST_PP_ARRAY_ENUM_TRAILING, and a version that uses it (this is now my favourite solution):

#define BOOST_PP_ARRAY_ENUM_TRAILING(array) \
    BOOST_PP_COMMA_IF(BOOST_PP_ARRAY_SIZE(array)) BOOST_PP_ARRAY_ENUM(array) \
    /**/

#define BAR(...) printf( \
    BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__) "\n" \
    BOOST_PP_ARRAY_ENUM_TRAILING(BOOST_PP_ARRAY_POP_FRONT( \
        BOOST_PP_VARIADIC_TO_ARRAY(__VA_ARGS__)))) \
    /**/

Towards Engineering Free/Libre Open Source Software (FLOSS) , The GCC project faced two alternatives: write its own C Standard library, or generate code that could have been linked to somebody else's C Standard library. For each language compiled by GCC for which there is a standard, GCCattempts to follow one or more versions of that standard, possiblywith some exceptions, and possibly with some extensions. 2.1 C Language. The original ANSI C standard (X3.159-1989) was ratified in 1989 andpublished in 1990.

The Definitive Guide to GCC, For example, GCC is the standard compiler shipped in every major and most minor As free software, GCC represents a compelling, attractive alternative to  Optimize various standard C string functions (e.g. strlen, strchr or strcpy) and their _FORTIFY_SOURCE counterparts into faster alternatives. Enabled at levels -O2, -O3. -fno-inline. Do not expand any functions inline apart from those marked with the always_inline attribute. This is the default when not optimizing.

GCC VAT Compliance (Basic): UAE Version, Alternative Basis of Calculation The standard method of tax apportionment may not be suitable for all partially exempt businesses because it may not reflect  To make the call safe regardless of the values of the two variables, the size of the destination buffer must be increased to at least 34 bytes. GCC includes the minimum size of the buffer in an informational note following the warning. An alternative to increasing the size of the destination buffer is to constrain the range of formatted values.

List of compilers, This page is intended to list all current compilers, compiler generators, interpreters, translators, ALGOL 68RS. Algol 68 GenieG, 2001, Full Language, NL, Includes standard collateral clause, Portable interpreter, GPL · C compiler. ^ Last Open64 v5.0 uses GCC 4.2 as its Front End, which doesn't support any C​++11. 2 Language Standards Supported by GCC. For each language compiled by GCC for which there is a standard, GCC attempts to follow one or more versions of that standard, possibly with some exceptions, and possibly with some extensions. 2.1 C Language. The original ANSI C standard (X3.159-1989) was ratified in 1989 and published in 1990.

C++17, C++17 is a revision of the ISO/IEC 14882 standard for the C++ programming language. Making the text message for static_assert optional; Allow typename (​as an alternative to class ) in a template template parameter; New rules for GCC has had almost complete support for C++17 language features since version 7. The GNU Compiler Collection (GCC) is a compiler system produced by the GNU Project supporting various programming languages. GCC is a key component of the GNU toolchain. As well as being the official compiler of the unfinished GNU operating system, GCC has been adopted as the standard compiler by most other modern Unix-like computer operating

Comments
  • Why use BAR instead of FOO in the first place?
  • @GMan: I added an example at the end
  • @GMan: Read the last sentence (:
  • This feature has been proposed for inclusion in C2x.
  • @zwol the latest version submitted to WG14 looks like this, which uses a new syntax based on the __VA_OPT__ keyword. This has already been "adopted" by C++, so I expect C will follow suit. (don't know whether that means it was fast-tracked into C++17 or if it's set for C++20 though)
  • Judging by my disability to find a solution on the web and the lack of answers here, I guess you're right ):
  • Is n976 what you are referring to? I searched the rest of the C working group's documents for a response but never found one. It wasn't even in the agenda for the subsequent meeting. The only other hit on this topic was Norway's comment #4 in n868 back from before C99 was ratified (again with no follow-up discussion).
  • Yes, specifically the second half of that. There may have been discussion on comp.std.c but I was unable to find any in Google Groups just now; it certainly never got any attention from the actual committee (or if it did, nobody ever told me about it).
  • I'm afraid I don't have a proof, nor am I anymore the right person to try to think one up. I did write half of GCC's preprocessor, but that was more than ten years ago, and I'd never have thought of the argument-counting trick below, even then.
  • This extension works with clang & intel icc compilers, as well as gcc.
  • Note that this will fail if you call BAR with 10 or more arguments, and though it's relatively easy to extend to more arguments, it will always have a upper bound on the number of arguments it can deal with
  • @ChrisDodd: Correct. Unfortunately, there doesn't appear to be a way to avoid a limit in the number of arguments without relying on compiler-specific extensions. Also, I'm unaware of a way to reliably test if there are too many arguments (so that a useful compiler error message can be printed, rather than a strange failure).
  • the problem with this extra 0 is that it will actually end up in the code if it calls vararg function. Check for solution provided by Richard Hansen
  • @Pavel is correct about the second example, but the first works great. +1.