Useful C Debug Macro

Tonight I took the plunge to get back into some more C coding. In getting my environment setup I came across a useful debugging macro. This macro will output the filename and line number every time it’s expanded. I wanted to make sure I understood how the macro was working before just copying and pasting it into my source code so I’ve broken it down below for myself and others to understand.

Here is a copy of the code that I slightly modified to also include the function name from where the debug macro is being used.

#ifdef DEBUG
    #define _DEBUG(fmt, args...) printf("%s:%s:%d: "fmt, __FILE__, __FUNCTION__, __LINE__, args)
#else
    #define _DEBUG(fmt, args...)
#endif

First we check if the DEBUG macro has been defined at all. If it has been, we declare a function-like _DEBUG macro that will get expanded to our debugging function. If DEBUG has not been defined, we still declare our function-like macro the same but with just no body so the macro will not be expanded to anything.

Our _DEBUG macro makes use of a few predefined macros:

__FILE__: Expands to the current file name. This will not print the shortname of the file.

__FUNCTION__: Expands to the current function the code is being executed from. This is a C99 and GCC feature only.

__LINE__: Expands to the current line number in the file

We also make use of ‘variadic macros’ aka macros that accept a variable number of arguments. A variadic macro can be defined named or unnamed. We use the named method which involves putting an argument name followed by ‘…’ which is later referenced by just using the argument name in the macro body. An unnamed variadic macro just involves using ‘…’ and later referenced in the macro body using the predefined macro VA_ARGS

A default format string is passed into printf to take care of the formatting for the filename, function name and line number. Immediately after the default format string, we specify the fmt argument we used that will get assigned our own format string that we pass into the _DEBUG macro. This will all get expanded to “%s:%s:%d: “ “val of fmt” which is valid C syntax.

To activate the _DEBUG macro we can define DEBUG in our gcc command

    gcc -g -D DEBUG