Macros with a variable number of arguments

  • Thread starter Augustus S.F.X Van Dusen
  • Start date
A

Augustus S.F.X Van Dusen

I have recently come across the following construction:

#define P_VAR(output, string, args...) \
fprintf (output, "This is "string"\n", ##args)

which can be invoked as follows:

int x = 1, y = 2 ;
char * str = "String" ;

P_VAR(stdout, "x: %d", x) ;
P_VAR(stdout, "y: %d", y) ;
P_VAR(stderr, "str: %s, x: %d, y: %d", str, x, y) ;

printing

This is x: 1
This is y: 2
This is str: String, x: 1, y: 2

Is this ANSI C? Can it be generalized to work with just two arguments?
That is, when there are no optional arguments args?
 
J

John Cochran

I have recently come across the following construction:

#define P_VAR(output, string, args...) \
fprintf (output, "This is "string"\n", ##args)

which can be invoked as follows:

int x = 1, y = 2 ;
char * str = "String" ;

P_VAR(stdout, "x: %d", x) ;
P_VAR(stdout, "y: %d", y) ;
P_VAR(stderr, "str: %s, x: %d, y: %d", str, x, y) ;

printing

This is x: 1
This is y: 2
This is str: String, x: 1, y: 2

Is this ANSI C? Can it be generalized to work with just two arguments?
That is, when there are no optional arguments args?

Yes and No.

The specific syntax being used is GCC specific. ANSI C (1999 standard)
has variable argument macros with a different syntax (which modern GCC
supports).

Old GCC syntax...
#define P_VAR(output, string, args...) \
fprintf (output, "This is "string"\n", ##args)

The "##" in the above macro is GCCs method of dealing with the case where
the variable part of the macro is empty. It has the effect of deleting the
comma just prior to the "##" when args is empty.


ANSI C and new GCC syntax
#define P_VAR(output, ...) \
fprintf (output, "This is "string"\n", __VA_ARGS__)

This definition of P_VAR has the identical expansion as the previous definition
of P_VAR. Both require a minimum of 2 parameters when being expanded.

The Old GCC version has the advantage that it's closer to what you expect
from experience with printf() and company, but suffers from the kludge
needed when the variable part of the macro is empty.

The ANSI C version doesn't have the "empty kludge", but requires one more
parameter than the number of named parameters. For example let's say that
I want to create a "log" macro that is used in the exact same fashion as
printf() except it sends all output to log_file instead of stdout. The
desired macro would look like:

#define log(...) fprintf(log_file, __VA_ARGS__)

And yes, the log macro would require at least 1 parameter in order to be
legal just as printf() requires at least 1 parameter.

Using the old GCC style the macro would be

#define log(format, args...) fprintf(log_file, format, ##args)

I would suggest that you use the new ANSI method of variable argument macros
instead of the old GCC style since it is likely to be supported by more
compilers in the future.
 
A

Augustus S.F.X Van Dusen

Thanks so much for your answer. The __VAR_ARGS__ approach, that I was not
aware of, is more appropriate to my purposes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,060
Latest member
BuyKetozenseACV

Latest Threads

Top