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

Macro Variable Argument List with __FILE__ and __LINE__

P: n/a
I couldn't find an example of this anywhere so I post it in the hope
that someone finds it useful. I believe this is compiler specific (I'm
using gcc), as C99 defines __VA_ARGS__. Comments are welcome.

This will print the file name and line number followed by a format
string and a variable number of arguments. The key here is that you
MUST have a space between __LINE__ and the last comma, otherwise
__LINE__ gets eaten by the ## if args is empty. It took me awhile to
figure that out.

#define DEBUGLOG(fmt, args...) printf("%s(%d)"fmt , __FILE__ ,
__LINE__ , ## args)

I'm curious, does anyone know if the equivelant can be done using
__VA_ARGS__?

Nov 14 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
jake1138 wrote:
I couldn't find an example of this anywhere so I post it in the hope
that someone finds it useful. I believe this is compiler specific (I'm
using gcc), as C99 defines __VA_ARGS__. Comments are welcome.

This will print the file name and line number followed by a format
string and a variable number of arguments. The key here is that you
MUST have a space between __LINE__ and the last comma, otherwise
__LINE__ gets eaten by the ## if args is empty. It took me awhile to
figure that out.

#define DEBUGLOG(fmt, args...) printf("%s(%d)"fmt , __FILE__ ,
__LINE__ , ## args)

I'm curious, does anyone know if the equivelant can be done using
__VA_ARGS__?


I do.
Probably you want to know whether it can be done: Yes, it can be done.

If you want to know how:
#define DEBUGLOG(fmt, ...) \
printf("%s(%d)"fmt, __FILE__, __LINE__, __VA_ARGS__)

(untested)
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #2

P: n/a
>jake1138 wrote:
This [gcc-specific trick] will print the file name and line number
followed by a format string and a variable number of arguments. ...
[formatting broken originally by google, now fixed:]
#define DEBUGLOG(fmt, args...) \
printf("%s(%d)"fmt , __FILE__ , __LINE__ , ## args)

I'm curious, does anyone know if the equivelant can be done using
__VA_ARGS__?

In article <36*************@individual.net>
Michael Mair <Mi**********@invalid.invalid> wrote:I do.
Probably you want to know whether it can be done: Yes, it can be done.

If you want to know how:
#define DEBUGLOG(fmt, ...) \
printf("%s(%d)"fmt, __FILE__, __LINE__, __VA_ARGS__)

(untested)


This is not quite equivalent. GCC's special "prefix ##" syntax
means "remove the preceding pp-token if the variable arguments
are missing". Hence, if one writes:

DEBUGLOG("got here\n");

with the gcc version, one gets:

printf("%s(%d)""got here", __FILE__, __LINE);

but the C99 version produces:

printf("%s(%d)""got here", __FILE__, __LINE,);

which is not syntactically valid.

There appears to be no way to achieve the desired effect in C99.
As a workaround, one can write:

#define DEBUGLOG(...) \
(printf("%s(%d)", __FILE__, __LINE), printf(__VA_ARGS__))

In other words, just use two calls. Or instead of calling printf()
directly, call your own function that takes three-or-more arguments:

extern int debuglog(const char *, int, const char *, ...);
#define DEBUGLOG(...) debuglog(__FILE__, __LINE__, __VA_ARGS__)

In either case, __VA_ARGS__ will necessarily expand to at least one
parameter, so that the "remove preceding pp-token" behavior is never
needed.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #3

P: n/a
Chris Torek wrote:
jake1138 wrote:
This [gcc-specific trick] will print the file name and line number
followed by a format string and a variable number of arguments. ...

[formatting broken originally by google, now fixed:]

#define DEBUGLOG(fmt, args...) \
printf("%s(%d)"fmt , __FILE__ , __LINE__ , ## args)

I'm curious, does anyone know if the equivelant can be done using
__VA_ARGS__?

In article <36*************@individual.net>
Michael Mair <Mi**********@invalid.invalid> wrote:
I do.
Probably you want to know whether it can be done: Yes, it can be done.

If you want to know how:
#define DEBUGLOG(fmt, ...) \
printf("%s(%d)"fmt, __FILE__, __LINE__, __VA_ARGS__)

(untested)

This is not quite equivalent. GCC's special "prefix ##" syntax
means "remove the preceding pp-token if the variable arguments
are missing". Hence, if one writes:

DEBUGLOG("got here\n");

with the gcc version, one gets:

printf("%s(%d)""got here", __FILE__, __LINE);

but the C99 version produces:

printf("%s(%d)""got here", __FILE__, __LINE,);

which is not syntactically valid.

There appears to be no way to achieve the desired effect in C99.
As a workaround, one can write:

#define DEBUGLOG(...) \
(printf("%s(%d)", __FILE__, __LINE), printf(__VA_ARGS__))

In other words, just use two calls. Or instead of calling printf()
directly, call your own function that takes three-or-more arguments:

extern int debuglog(const char *, int, const char *, ...);
#define DEBUGLOG(...) debuglog(__FILE__, __LINE__, __VA_ARGS__)

In either case, __VA_ARGS__ will necessarily expand to at least one
parameter, so that the "remove preceding pp-token" behavior is never
needed.


Thank you very much!
I never used this gcc extension (-std=cXX -pedantic...), so I was
too quick with my assumptions.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #4

P: n/a
"jake1138" <co******@gmail.com> wrote:
# I couldn't find an example of this anywhere so I post it in the hope
# that someone finds it useful. I believe this is compiler specific (I'm
# using gcc), as C99 defines __VA_ARGS__. Comments are welcome.
#
# This will print the file name and line number followed by a format
# string and a variable number of arguments. The key here is that you
# MUST have a space between __LINE__ and the last comma, otherwise
# __LINE__ gets eaten by the ## if args is empty. It took me awhile to
# figure that out.
#
# #define DEBUGLOG(fmt, args...) printf("%s(%d)"fmt , __FILE__ ,
# __LINE__ , ## args)

Alternatively,

debug.h
typedef void (*DebugLogFormat)(char *format,...);
DebugLogFormat debugLogSetup(char *file,int line);
#define DEBUGLOG (debugLogSetup(__FILE__,__LINE__))
debug.c
static char *file; static int line;
static void debugLogFormat(char *format,...) {
printf("[%s:%d] ",file,line);
va_list list; va_start(list,format);
vprintf(format,list);
va_end(list);
}
DebugLogFormat debugLogSetup(char *file0,int line0) {
file = file0; line = line0;
return debugLogFormat;
}

--
SM Ryan http://www.rawbw.com/~wyrmwif/
A bunch of savages in this town.
Nov 14 '05 #5

P: n/a
On Mon, 07 Feb 2005 12:05:08 -0000, SM Ryan
<wy*****@tango-sierra-oscar-foxtrot-tango.fake.org> wrote:
<snip>
Alternatively,

debug.h
typedef void (*DebugLogFormat)(char *format,...);
DebugLogFormat debugLogSetup(char *file,int line);
#define DEBUGLOG (debugLogSetup(__FILE__,__LINE__))
debug.c
static char *file; static int line;
static void debugLogFormat(char *format,...) {
printf("[%s:%d] ",file,line);
va_list list; va_start(list,format);
vprintf(format,list);
va_end(list);
}
DebugLogFormat debugLogSetup(char *file0,int line0) {
file = file0; line = line0;
return debugLogFormat;
}


Not safe for threading, which is not in standard C but is in many C
systems and programs. Why not just

..h
typedef int like_printf (const char * /*restrict*/, ...);
like_printf * logPrefix (const char * file, /*unsigned?*/long line);
#define DEBUGLOG logPrefix(__FILE__,__LINE__) /*printfargs*/
..c
like_printf * logPrefix (const char * file, long line)
{ printf ("[%s:%ld] ", file, line); return printf; }
or even
static bool logflag = false;
/* some way to set to true -- or viceversa */
static int dont_printf (const char * /*restrict*/ fmt, ...)
{ return 0; }
like_printf * logPrefix (const char * file, /*ditto*/long line)
{ if( !logflag ) return dont_printf;
/*else*/ /*as before*/ }

Note that this evaluates the log-data arguments even if logging is
disabled by the flag; dont_printf is actually called but discards the
values. This may be costly and generally it is bad style to have
needed sideeffects in statements whose apparent purpose is debugging;
OTOH macro schemes that suppress the evaluation need to be tested in
(only?) the release version, or code-reviewed carefully, or both, to
ensure that they don't have such bugs.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.