Macro Variable Argument List with __FILE__ and __LINE__

Discussion in 'C Programming' started by jake1138, Feb 4, 2005.

  1. jake1138

    jake1138 Guest

    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__?
    jake1138, Feb 4, 2005
    #1
    1. Advertising

  2. jake1138

    Michael Mair Guest

    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.
    Michael Mair, Feb 4, 2005
    #2
    1. Advertising

  3. jake1138

    Chris Torek Guest

    >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 <>
    Michael Mair <> 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 (40°39.22'N, 111°50.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.
    Chris Torek, Feb 4, 2005
    #3
  4. jake1138

    Michael Mair Guest

    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 <>
    > Michael Mair <> 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.
    Michael Mair, Feb 5, 2005
    #4
  5. jake1138

    SM Ryan Guest

    "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)

    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.
    SM Ryan, Feb 7, 2005
    #5
  6. On Mon, 07 Feb 2005 12:05:08 -0000, SM Ryan
    <> 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
    Dave Thompson, Feb 14, 2005
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Spry
    Replies:
    1
    Views:
    935
    Richard Heathfield
    Jul 26, 2003
  2. Joakim Hove
    Replies:
    4
    Views:
    8,072
    Maric Michaud
    Aug 13, 2006
  3. Kenneth Brody

    __FILE__ and __LINE__ within macros

    Kenneth Brody, Apr 4, 2006, in forum: C Programming
    Replies:
    7
    Views:
    791
    Keith Thompson
    Apr 5, 2006
  4. Neo

    __FILE__ and __LINE__

    Neo, Nov 29, 2006, in forum: C++
    Replies:
    5
    Views:
    739
    Default User
    Nov 29, 2006
  5. Bill Davy
    Replies:
    14
    Views:
    1,674
    alain
    Feb 14, 2008
Loading...

Share This Page