By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,905 Members | 1,743 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,905 IT Pros & Developers. It's quick & easy.

variadic macros and and empty replacement for __VA_ARGS__

P: n/a
I want to write a macro that produces debug output and has a variable
number of arguments, so that I can use like this:

int i;
char *s;

DBG("simple message\n");
DBG("message with an int argument, value is %d\n", i);
DBG("two arguments: int %d, strings %s\n", i, s);

The output should be a fixed prefix, say "DEBUG ", followed by the
function name the macros is used in, and then by the string passed to
the macro, including further arguments.

The best solution I have found so far, is

#define DBG(fmt, ...) printf("DEBUG %s:" fmt, __func__, __VA_ARGS__)

This works as intended as long as there is at least one argument
following the format strings, but it expands to
printf("DEBUG %s:" fmt, __func__,) when there is no argument and that
causes a syntax error.

The draft of C99 I have here, disallows to give no arguments for the
ellipsis ... as stated in 6.10.3:

[#4] If the identifier-list in the macro definition does not end
with an ellipsis, the number of arguments, including those
arguments consisting of no preprocessing tokens, in an invocation
of a function-like macro shall agree with the number of parameters
in the macro definition. Otherwise, there shall be more arguments
in the invocation than there are parameters in the macro
definition (excluding the ...). There shall exist a )
preprocessing token that terminates the invocation.
Is there a better way to write the DBG() macro to avoid this?

urs
Mar 27 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Urs Thuermann <ur*@isnogud.escape.de> writes:
I want to write a macro that produces debug output and has a variable
number of arguments, so that I can use like this:

int i;
char *s;

DBG("simple message\n");
DBG("message with an int argument, value is %d\n", i);
DBG("two arguments: int %d, strings %s\n", i, s);

The output should be a fixed prefix, say "DEBUG ", followed by the
function name the macros is used in, and then by the string passed to
the macro, including further arguments.

The best solution I have found so far, is

#define DBG(fmt, ...) printf("DEBUG %s:" fmt, __func__, __VA_ARGS__)
<SNIP> Is there a better way to write the DBG() macro to avoid this?

There was a related thread a couple of weeks ago:

<http://groups.google.co.uk/group/comp.lang.c/browse_frm/thread/ac0bda529a91d754/949239c624c9fe71?lnk=st&q=logging+group%3Acomp.lan g.c&rnum=3&hl=en#949239c624c9fe71>

This basically used a *function* instead of a macro. The logging
function accepts variadic arguments, and these can then be modified
and passed on to a varargs form of printf (e.g. vfprintf).

--

John Devereux
Mar 27 '06 #2

P: n/a
On 2006-03-27, John Devereux <jd******@THISdevereux.me.uk> wrote:
Urs Thuermann <ur*@isnogud.escape.de> writes:
I want to write a macro that produces debug output and has a variable
number of arguments, so that I can use like this:

int i;
char *s;

DBG("simple message\n");
DBG("message with an int argument, value is %d\n", i);
DBG("two arguments: int %d, strings %s\n", i, s);

The output should be a fixed prefix, say "DEBUG ", followed by the
function name the macros is used in, and then by the string passed to
the macro, including further arguments.

The best solution I have found so far, is

#define DBG(fmt, ...) printf("DEBUG %s:" fmt, __func__, __VA_ARGS__)

<SNIP>
Is there a better way to write the DBG() macro to avoid this?

There was a related thread a couple of weeks ago:

<http://groups.google.co.uk/group/comp.lang.c/browse_frm/thread/ac0bda529a91d754/949239c624c9fe71?lnk=st&q=logging+group%3Acomp.lan g.c&rnum=3&hl=en#949239c624c9fe71>

This basically used a *function* instead of a macro. The logging
function accepts variadic arguments, and these can then be modified
and passed on to a varargs form of printf (e.g. vfprintf).


One little thing you might consider at an early stage : have an
importance or category enum as the first/second parameter : very
useful for filtering/enabling/disabling runtime logging for different
subsets in a non trivial system. You might even use the function name
and have settings to enable/disable logging for the particular function.
Mar 27 '06 #3

P: n/a
> This works as intended as long as there is at least one argument
following the format strings, but it expands to
printf("DEBUG %s:" fmt, __func__,) when there is no argument and that
causes a syntax error.


#define macroFunc(a,b,...) ( Func(a, b, ##__VA_ARGS__) )

Mar 27 '06 #4

P: n/a
John Devereux wrote:
Urs Thuermann <ur*@isnogud.escape.de> writes:
I want to write a macro that produces debug output and has a variable
number of arguments, so that I can use like this:

int i;
char *s;

DBG("simple message\n");
DBG("message with an int argument, value is %d\n", i);
DBG("two arguments: int %d, strings %s\n", i, s);

The output should be a fixed prefix, say "DEBUG ", followed by the
function name the macros is used in, and then by the string passed to
the macro, including further arguments.

The best solution I have found so far, is

#define DBG(fmt, ...) printf("DEBUG %s:" fmt, __func__, __VA_ARGS__)

<SNIP>
Is there a better way to write the DBG() macro to avoid this?

There was a related thread a couple of weeks ago:

<http://groups.google.co.uk/group/comp.lang.c/browse_frm/thread/ac0bda529a91d754/949239c624c9fe71?lnk=st&q=logging+group%3Acomp.lan g.c&rnum=3&hl=en#949239c624c9fe71>

This basically used a *function* instead of a macro. The logging
function accepts variadic arguments, and these can then be modified
and passed on to a varargs form of printf (e.g. vfprintf).


See this one too:

http://groups.google.co.uk/group/com...d17634c1ed7065

--
==============
Not a pedant
==============
Mar 27 '06 #5

P: n/a
raxip schrieb:
This works as intended as long as there is at least one argument
following the format strings, but it expands to
printf("DEBUG %s:" fmt, __func__,) when there is no argument and that
causes a syntax error.


#define macroFunc(a,b,...) ( Func(a, b, ##__VA_ARGS__) )


This is "gcc-C".
It is not valid C99, though.

-Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Mar 27 '06 #6

P: n/a
Assumptions are wonderous creatures.

Mar 27 '06 #7

P: n/a
raxip wrote:
Assumptions are wonderous creatures.


That's nice. What does it have to do with anything? See my .sig below
for valuable information.

Brian

--
Please quote enough of the previous message for context. To do so from
Google, click "show options" and use the Reply shown in the expanded
header.
Mar 27 '06 #8

P: n/a
> That's nice. What does it have to do with anything? See my .sig below
for valuable information.


Is this better?

Mar 27 '06 #9

P: n/a
raxip wrote:
That's nice. What does it have to do with anything? See my .sig
below for valuable information.


Is this better?


Somewhat. Where are the attributions (the who said what part)? I know
that Google puts them in if you use the correct Reply.

Brian
Mar 27 '06 #10

P: n/a
Michael Mair wrote:
raxip schrieb:
This works as intended as long as there is at least one argument
following the format strings, but it expands to
printf("DEBUG %s:" fmt, __func__,) when there is no argument and that
causes a syntax error.


#define macroFunc(a,b,...) ( Func(a, b, ##__VA_ARGS__) )


This is "gcc-C".
It is not valid C99, though.


I believe it can be valid C99 if the result of macroFunc(...) is
stringized, and __VA_ARGS__ is empty. (Of course, in that case, it's
useless and doesn't answer the question.)

As for the original question, I had taken a look at a non-GCC way of
writing ,##__VA_ARGS__ earlier. I don't recommend anyone actually use
this for hopefully obvious reasons, but in case anyone cares, here it
is. Please let me know if there are bugs in it (there may well be).

#include <stdio.h>

#define CONCAT(x, y) CONCAT_(x, y)
#define CONCAT_(x, y) x##y

#define ID(...) __VA_ARGS__

#define IFMULTIARG(if,then,else) \
CONCAT(IFMULTIARG_, IFMULTIARG_(if, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 0, ))(then,else)
#define IFMULTIARG_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, \
_10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
_30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
_50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
_60, _61, _62, _63, ...) _63
#define IFMULTIARG_0(then, else) else
#define IFMULTIARG_1(then, else) then

#define PROVIDE_SECOND_ARGUMENT(x, ...) \
CONCAT(IFMULTIARG(ID(__VA_ARGS__), INSERT_, ADD_), \
SECOND_ARGUMENT) (x, __VA_ARGS__)
#define ADD_SECOND_ARGUMENT(x, y) y, x
#define INSERT_SECOND_ARGUMENT(x, y, ...) y, x, __VA_ARGS__

#define DEBUG(...) printf("DEBUG %s: " \
PROVIDE_SECOND_ARGUMENT(__func__, __VA_ARGS__))

int main() {
DEBUG("1\n");
DEBUG("%d\n", 2);
DEBUG("%d %d\n", 1, 2);
}

Mar 27 '06 #11

P: n/a
Groovy hepcat Urs Thuermann was jivin' on 27 Mar 2006 15:34:46 +0200
in comp.lang.c.
variadic macros and and empty replacement for __VA_ARGS__'s a cool
scene! Dig it!
I want to write a macro that produces debug output and has a variable
number of arguments, so that I can use like this:

int i;
char *s;

DBG("simple message\n");
DBG("message with an int argument, value is %d\n", i);
DBG("two arguments: int %d, strings %s\n", i, s);

The output should be a fixed prefix, say "DEBUG ", followed by the
function name the macros is used in, and then by the string passed to
the macro, including further arguments.


I think this should work:

#define DBG(...) printf("DEBUG $s: ", __func__), printf(__VA_ARGS__)

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Mar 29 '06 #12

P: n/a
> I think this should work:

#define DBG(...) printf("DEBUG $s: ", __func__), printf(__VA_ARGS__)


This is the first answer in this thread, which seems to understand my
post and solves the problem of inserting the __func__ between the fmt
and __VA_ARGS__ without having the ,) when __VA_ARGS__ is empty.

I wanted to avoid calling printf() twice, because I need this in the
linux kernel (with printk instead of printf) and I'd prefer it to be
atomic. Also, I can't make a function debug(char *name, char *fmt, ...)
and call printk() from there, because the linux kernel doesn't have
vprintk().

But I will follow your suggesstion and will do it like follows:

#ifdef DEBUG
int debug = 0;
#define DBG(...) (debug & 1 ? (printk(KERN_DEBUG "%s: ", __func__), \
printk(__VA_ARGS__)) : 0)
#else
#define DBG(...)
#endif

where KERN_DEBUG is a string constant defined in the linux kernel
sources.

urs
Mar 31 '06 #13

P: n/a
Couldn't you get rid of the int debug = 0 using this?:

#define DEBUG 1

#ifdef DEBUG
#define DBG(...) (DEBUG ? (printk(KERN_DEBUG "%s: ", __func__), \
printk(__VA_ARGS__)) : 0)
#else
#define DBG(...)
#endif

Mar 31 '06 #14

P: n/a
pemo wrote:

Urs Thuermann wrote:
I think this should work:

#define DBG(...) printf("DEBUG $s: ", __func__), printf(__VA_ARGS__)


This is the first answer in this thread, which seems to understand my
post and solves the problem of inserting the __func__ between the fmt
and __VA_ARGS__ without having the ,) when __VA_ARGS__ is empty.

I wanted to avoid calling printf() twice, because I need this in the
linux kernel (with printk instead of printf) and I'd prefer it to be
atomic. Also, I can't make a function debug(char *name, char *fmt, ...)
and call printk() from there, because the linux kernel doesn't have
vprintk().

But I will follow your suggesstion and will do it like follows:

#ifdef DEBUG
int debug = 0;
#define DBG(...) (debug & 1 ? (printk(KERN_DEBUG "%s: ", __func__), \
printk(__VA_ARGS__)) : 0)
#else
#define DBG(...)
#endif

where KERN_DEBUG is a string constant defined in the linux kernel
sources.

Couldn't you get rid of the int debug = 0 using this?:

#define DEBUG 1

#ifdef DEBUG
#define DBG(...) (DEBUG ? (printk(KERN_DEBUG "%s: ", __func__), \
printk(__VA_ARGS__)) : 0)
#else
#define DBG(...)
#endif

Apr 1 '06 #15

P: n/a
"pemo" <us***********@gmail.com> writes:
Couldn't you get rid of the int debug = 0 using this?:

#define DEBUG 1

#ifdef DEBUG
#define DBG(...) (DEBUG ? (printk(KERN_DEBUG "%s: ", __func__), \
printk(__VA_ARGS__)) : 0)
#else
#define DBG(...)
#endif


No, your code doesn't make sense.

In my code, debug is initialized to zero (i.e. no debug output) but
can be set at module load time. There are other debug macros, that
test for debug&2 and debug&4.

urs
Apr 3 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.