Related
The <stdarg.h> header file is used to make functions accept undefined number of arguments, right?
So, the printf() funtion of <stdio.h> must be using <stdarg.h> to accept avariable number of arguments(please correct me if I'm mistaken).
I found the following lines in the stdio.h file of gcc:
#if defined __USE_XOPEN || defined __USE_XOPEN2K8
# ifdef __GNUC__
# ifndef _VA_LIST_DEFINED
typedef _G_va_list va_list;
# define _VA_LIST_DEFINED
# endif
# else
# include <stdarg.h>//////////////////////stdarg.h IS INCLUDED!///////////
# endif
#endif
I can't understand most of what's in it, but it appears to be including <stdarg.h>
So, if printf() uses <stdarg.h> for accepting variable number of arguments and stdio.h has printf(), a C program using printf() need not include <stdarg.h> does it?
I tried a program which had printf() and a user-defined function accepting variable number of arguments.
The program I tried is:
#include<stdio.h>
//#include<stdarg.h>///If this is included, the program works fine.
void fn(int num, ...)
{
va_list vlist;
va_start(vlist, num);//initialising va_start (predefined)
int i;
for(i=0; i<num; ++i)
{
printf("%d\n", va_arg(vlist, int));
}
va_end(vlist);//clean up memory
}
int main()
{
fn(3, 18, 11, 12);
printf("\n");
fn(6, 18, 11, 32, 46, 01, 12);
return 0;
}
It works fine if <stdarg.h> is included but otherwise generates the following error:
40484293.c:13:38: error: expected expression before ‘int’
printf("%d\n", va_arg(vlist, int));//////error: expected expression before 'int'/////////
^~~
How is this?
Or is it that printf() doesn't use <stdarg.h> for accepting variable number of arguments?
If so, how is it done?
Consider:
stdio.h:
int my_printf(const char *s, ...);
Do you need <stdarg.h>? No, you don't. ... is part of the grammar of the language - it's "built-in". However, as soon as you want to do anything meaningful and portable with such list of arguments, you need the names defined in there: va_list, va_start and so on.
stdio.c:
#include "stdio.h"
#include "stdarg.h"
int my_printf(const char *s, ...)
{
va_list va;
va_start(va, s);
/* and so on */
}
But this will be necessary, essentially, in the implementation of your libc which is something you don't see unless you compile the library on your own. What you instead get is the libc shared library, which has already been compiled to machine code.
So, if printf() uses for accepting variable number of
arguments and stdio.h has printf(), a C program using printf() need
not include does it?
Even if it were so, you cannot rely on that, otherwise your code is ill-formed: you must include all the headers anyway if a name belonging to them is used, regardless whether the implementation already does that or not.
I'm first going to answer your question in terms of the C standard, because that is what tells you how you should write your code.
The C standard requires stdio.h to "behave as-if" it does not include stdarg.h. In other words, the macros va_start, va_arg, va_end, and va_copy, and the type va_list, are required not to be made available by including stdio.h. In other other words, this program is required not to compile:
#include <stdio.h>
unsigned sum(unsigned n, ...)
{
unsigned total = 0;
va_list ap;
va_start(ap, n);
while (n--) total += va_arg(ap, unsigned);
va_end(ap);
return total;
}
(This is a difference from C++. In C++, all standard library headers are allowed, but not required, to include each other.)
It is true that the implementation of printf (probably) uses the stdarg.h mechanism to access its arguments, but that just means that some files in the source code for the C library ("printf.c", perhaps) need to include stdarg.h as well as stdio.h; that doesn't affect your code.
It is also true that stdio.h declares functions that take va_list-typed arguments. If you look at those declarations, you will see that they actually use a typedef name that begins with either two underscores, or an underscore and a capital letter: for instance, with the same stdio.h you are looking at,
$ egrep '\<v(printf|scanf) *\(' /usr/include/stdio.h
extern int vprintf (const char *__restrict __format, _G_va_list __arg);
extern int vscanf (const char *__restrict __format, _G_va_list __arg);
All names that begin with two underscores, or an underscore and a capital letter, are reserved for the implementation - stdio.h is allowed to declare as many such names as it wants. Conversely, you, the application programmer, are not allowed to declare any such names, or use the ones that the implementation declares (except the subset that are documented, such as _POSIX_C_SOURCE and __GNUC__). The compiler will let you do it, but the effects are undefined.
Now I'm going to talk about the thing you quoted from stdio.h. Here it is again:
#if defined __USE_XOPEN || defined __USE_XOPEN2K8
# ifdef __GNUC__
# ifndef _VA_LIST_DEFINED
typedef _G_va_list va_list;
# define _VA_LIST_DEFINED
# endif
# else
# include <stdarg.h>
# endif
#endif
To understand what this is doing, you need to know three things:
Recent "issues" of POSIX.1, the official specification of what it means to be a "Unix" operating system, add va_list to the set of things stdio.h is supposed to define. (Specifically, in Issue 6, va_list is defined by stdio.h as an "XSI" extension, and in Issue 7 it's mandatory.) This code defines va_list, but only if the program has requested Issue 6+XSI or Issue 7 features; that's what #if defined __USE_XOPEN || defined __USE_XOPEN2K8 means. Notice that it is using _G_va_list to define va_list, just as, elsewhere, it used _G_va_list to declare vprintf. _G_va_list is already available somehow.
You cannot write the same typedef twice in the same translation unit. If stdio.h defined va_list without somehow notifying stdarg.h not to do it again,
#include <stdio.h>
#include <stdarg.h>
would not compile.
GCC comes with a copy of stdarg.h, but it does not come with a copy of stdio.h. The stdio.h you are quoting comes from GNU libc, which is a separate project under the GNU umbrella, maintained by a separate (but overlapping) group of people. Crucially, GNU libc's headers cannot assume that they are being compiled by GCC.
So, the code you quoted defines va_list. If __GNUC__ is defined, which means the compiler is either GCC or a quirk-compatible clone, it assumes that it can communicate with stdarg.h using a macro named _VA_LIST_DEFINED, which is defined if and only if va_list is defined — but being a macro, you can check for it with #if. stdio.h can define va_list itself and then define _VA_LIST_DEFINED, and then stdarg.h won't do it, and
#include <stdio.h>
#include <stdarg.h>
will compile fine. (If you look at GCC's stdarg.h, which is probably hiding in /usr/lib/gcc/something/something/include on your system, you will see the mirror image of this code, along with a hilariously long list of other macros that also mean "don't define va_list, I already did that" for other C libraries that GCC can, or could once, be used with.)
But if __GNUC__ is not defined, then stdio.h assumes it does not know how to communicate with stdarg.h. But it does know that it's safe to include stdarg.h twice in the same file, because the C standard requires that to work. So in order to get va_list defined, it just goes ahead and includes stdarg.h, and thus, the va_* macros that stdio.h isn't supposed to define will also be defined.
This is what the HTML5 people would call a "willful violation" of the C standard: it's wrong, on purpose, because being wrong in this way is less likely to break real-world code than any available alternative. In particular,
#include <stdio.h>
#include <stdarg.h>
is overwhelmingly more likely to appear in real code than
#include <stdio.h>
#define va_start(x, y) /* something unrelated to variadic functions */
so it's much more important to make the first one work than the second, even though both are supposed to work.
Finally, you might still be wondering where the heck _G_va_list came from. It's not defined anywhere in stdio.h itself, so it must either be a compiler intrinsic, or be defined by one of the headers stdio.h includes. Here's how you find out everything that a system header includes:
$ echo '#include <stdio.h>' | gcc -H -xc -std=c11 -fsyntax-only - 2>&1 | grep '^\.'
. /usr/include/stdio.h
.. /usr/include/features.h
... /usr/include/x86_64-linux-gnu/sys/cdefs.h
.... /usr/include/x86_64-linux-gnu/bits/wordsize.h
... /usr/include/x86_64-linux-gnu/gnu/stubs.h
.... /usr/include/x86_64-linux-gnu/gnu/stubs-64.h
.. /usr/lib/gcc/x86_64-linux-gnu/6/include/stddef.h
.. /usr/include/x86_64-linux-gnu/bits/types.h
... /usr/include/x86_64-linux-gnu/bits/wordsize.h
... /usr/include/x86_64-linux-gnu/bits/typesizes.h
.. /usr/include/libio.h
... /usr/include/_G_config.h
.... /usr/lib/gcc/x86_64-linux-gnu/6/include/stddef.h
.... /usr/include/wchar.h
... /usr/lib/gcc/x86_64-linux-gnu/6/include/stdarg.h
.. /usr/include/x86_64-linux-gnu/bits/stdio_lim.h
.. /usr/include/x86_64-linux-gnu/bits/sys_errlist.h
I used -std=c11 to make sure I was not compiling in POSIX Issue 6+XSI nor Issue 7 modes, and yet we see stdarg.h in this list anyway — not included directly by stdio.h, but by libio.h, which is not a standard header. Let's have a look in there:
#include <_G_config.h>
/* ALL of these should be defined in _G_config.h */
/* ... */
#define _IO_va_list _G_va_list
/* This define avoids name pollution if we're using GNU stdarg.h */
#define __need___va_list
#include <stdarg.h>
#ifdef __GNUC_VA_LIST
# undef _IO_va_list
# define _IO_va_list __gnuc_va_list
#endif /* __GNUC_VA_LIST */
So libio.h includes stdarg.h in a special mode (here's another case where implementation macros are used to communicate between system headers), and expects it to define __gnuc_va_list, but it uses it to define _IO_va_list, not _G_va_list. _G_va_list is defined by _G_config.h...
/* These library features are always available in the GNU C library. */
#define _G_va_list __gnuc_va_list
... in terms of __gnuc_va_list. That name is defined by stdarg.h:
/* Define __gnuc_va_list. */
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
typedef __builtin_va_list __gnuc_va_list;
#endif
And __builtin_va_list, finally, is an undocumented GCC intrinsic, meaning "whatever type is appropriate for va_list with the current ABI".
$ echo 'void foo(__builtin_va_list x) {}' |
gcc -xc -std=c11 -fsyntax-only -; echo $?
0
(Yes, GNU libc's implementation of stdio is way more complicated than it has any excuse for being. The explanation is that back in elder days people tried to make its FILE object directly usable as a C++ filebuf. That hasn't worked in decades — in fact, I'm not sure if it ever worked; it had been abandoned before EGCS, which is as far back as I know the history — but there are many, many vestiges of the attempt hanging around still, either for binary backward compatibility or because nobody has gotten around to cleaning them up.)
(Yes, if I'm reading this correctly, GNU libc's stdio.h won't work right with a C compiler whose stdarg.h doesn't define __gnuc_va_list. This is abstractly wrong, but harmless; anyone wanting a shiny new non-GCC-compatible compiler to work with GNU libc is going to have a whole lot more things to worry about.)
stdarg header file is used to make functions accept undefined number
of arguments, right?
No, <stdarg.h> just exposes an API that should be used to access extra arguments. There is no necessity to include that header if you want just declare function that accepts variable number of arguments, like this:
int foo(int a, ...);
This is a language feature and requires no extra declarations / definitions.
I found the following lines in the stdio.h file of gcc:
#if defined __USE_XOPEN || defined __USE_XOPEN2K8
# ifdef __GNUC__
# ifndef _VA_LIST_DEFINED
typedef _G_va_list va_list;
# define _VA_LIST_DEFINED
# endif
# else
# include <stdarg.h>//////////////////////stdarg.h IS INCLUDED!///////////
# endif
#endif
I guess this stuff is required only to declare things like vprintf() without internal including of <stdarg.h>:
int vprintf(const char *format, va_list ap);
To top it off:
Header that declares function with variable number of arguments shouldn't include <stdarg.h> internally.
Implementation of function with variable number of arguments must include <stdarg.h> and use va_list API to access extra arguments.
No, to use printf() all you need is #include <stdio.h>. There's no need for stdarg because printf is already compiled. The compiler only needs to see a prototype for printf to know that it is variadic (derived from the ellipsis ... in the prototype). If you look at the stdio library source code for printf you'll see the <stdarg.h> being included.
If you want to write your own variadic function, you must #include <stdarg.h> and use its macros accordingly. As you can see, if you forget to do that, the va_start/list/end symbols are unknown to the compiler.
If you want to see a real implementation of printf, look at the code in FreeBSD's standard I/O source, along with the source for vfprintf.
Fundamentals of splitting a module into a header file and a source file:
In the header file, you put only the interface of your module
In the source file, you put the implementation of your module
So even if the implementation of printf makes use of va_arg as you speculate:
In stdio.h, the author only declared int printf(const char* format, ...);
In stdio.c, the author implemented printf using va_arg
This implementation of stdio.h does not include stdarg.h when compiled with gcc. It works by magic that compiler writers always have up their sleeves.
Your C source files must include every system header they reference anyway. It is a requirement of the C standard. That is, if your source code requires definitions present in stdarg.h, it must contain #include <stdarg.h> directive either directly, or in one of your header files that it includes. It cannot rely on stdarg.h being included in other standard headers, even if they do in fact include it.
The <stdarg.h> file is required to be included only if you are going to implement a variable number of arguments function. It's not required to be able to use printf(3) and friends. Only if you are going to process arguments on a variable number of args function, you'll need the va_list type, and the va_start, va_arg and va_end macros. So, only then you'll need to forcibly include that file.
In general, you are not warranted that <stdarg.h> will be included with just including <stdio.h> Indeed, the code you cite only includes it, if __GNU_C__ is not defined (which I suspect, is the case, so it's not included in your case) and this macro is defined if you are using the gcc compiler.
If you are going to create variable argument passing functions in your code, the best approach is not to expect another included file to include it, but do it yourself (as a client for the requested functionality you are) everywhere you are using the va_list type, or va_start, va_arg or va_end macros.
In the past, there was some confusion about double inclusion, as some header files were not protected from double inclusion (including twice or more times the same include file produced errors about doubly defined macros or similar and you had to go with care) but today, this is not an issue and normally all standard header fields are protected from double inclusion.
Okay, there is the "regular" printf family: printf, fprintf, dprintf, sprintf, and snprintf.
And then there's the variable number of arguments printf family: vprintf, vfprintf, vdprintf, vsprintf, and vsnprintf.
To use a variable list of arguments with either, you need to declare stdarg.h.
stdarg.h defines all the macros you're using: va_list, va_start, va_arg, va_end, and va_copy.
This might sound like an interview question but is actually a practical problem.
I am working with an embedded platform, and have available only the equivalents of those functions:
printf()
snprintf()
Furthermore, the printf() implementation (and signature) is likely to change in the near future, so calls to it have to reside in a separate module in order to be easy to migrate later.
Given that, can I wrap logging calls in some function or macro? The goal is that my source code calls THAT_MACRO("Number of bunnies: %d", numBunnies); in a thousand places, but calls to the above functions are seen only in a single place.
Compiler: arm-gcc -std=c99
Edit: just to mention, but post 2000 best practices and probably a lot earlier, inline functions are far better than macros for numerous reasons.
There are 2 ways to do this:
Variadric macro
#define my_printf(...) printf(__VA_ARGS__)
function that forwards va_args
#include <stdarg.h>
#include <stdio.h>
void my_printf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
There are also vsnprintf, vfprintf and whatever you can think of in stdio.
Since you can use C99, I'd wrap it in a variadic macro:
#define TM_PRINTF(f_, ...) printf((f_), __VA_ARGS__)
#define TM_SNPRINTF(s_, sz_, f_, ...) snprintf((s_), (sz_), (f_), __VA_ARGS__)
since you didn't say that you have vprintf or something like it. If you do have something like it, you could wrap it in a function like Sergey L has provided in his answer.
The above TM_PRINTF does not work with an empty VA_ARGS list.
At least in GCC it is possible to write:
#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
The two ## signs remove the excess comma in front of them them if __VA_ARGS__ is empty.
If you can live with having to wrap the call in two parentheses, you can do it like this:
#define THAT_MACRO(pargs) printf pargs
Then use it:
THAT_MACRO(("This is a string: %s\n", "foo"));
^
|
OMG
This works since from the preprocessor's point of view, the entire list of arguments becomes one macro argument, which is substituted with the parenthesis.
This is better than just plain doing
#define THAT_MACRO printf
Since it allows you to define it out:
#define THAT_MACRO(pargs) /* nothing */
This will "eat up" the macro arguments, they will never be part of the compiled code.
UPDATE Of course in C99 this technique is obsolete, just use a variadic macro and be happy.
#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
The ## token will enable the usage TM_PRINTF("aaa");
#define PRINTF(...) printf(__VA_ARGS__)
This works like this:
It defines the parameterized macro PRINTF to accept (up to) infinite arguments, then preprocesses it from PRINTF(...) to printf(__VA_ARGS__). __VA_ARGS__ is used in parameterized macro definitions to denote the arguments given ('cause you can't name infinite arguments, can you?).
Limited library? Embedded system? Need as much performance as possible? No problem!
As demonstrated in this answer to this question, you can use assembly language to wrap function which do not accept VA_LIST into ones that do, implementing your own vprintf at little cost!
While this will work, and almost certainly result in the performance as well as abstraction you want, I would just recommend you get a more feature filled standard library, perhaps by slicing parts of uClibc. Such a solution is surely to be a more portable and overall more useful answer than using assembly, unless you absolutely need every cycle.
That's why such projects exist, after all.
This is a slightly modified version of #ldav1's excellent answer which prints time before the log:
#define TM_PRINTF(f_, ...) \
{ \
struct tm _tm123_; \
struct timeval _xxtv123_; \
gettimeofday(&_xxtv123_, NULL); \
localtime_r(&_xxtv123_.tv_sec, &_tm123_); \
printf("%2d:%2d:%2d.%d\t", _tm123_.tm_hour, _tm123_.tm_min, _tm123_.tm_sec, _xxtv123_.tv_usec); \
printf((f_), ##__VA_ARGS__); \
};
Below is an example wrapper for the vsprintf() function, from https://www.cplusplus.com/reference/cstdio/vsprintf/:
#include <stdio.h>
#include <stdarg.h>
void PrintFError ( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
perror (buffer);
va_end (args);
}
Following the example above, one can implement wrappers for other desired functions from <stdio.h>.
What MACRO can be used to switch off printf statements, rather than removing them all for deployment builds, I just want to switch them off, skip them, ignore them.
EDIT: I personally use gcc, but code is part of a larger project which will be compiled on a Panda board running Ubuntu.
Not exactly what you ask for, but I use this construct in my code for debug output when I do not have a proper logging system handy:
#if 1
#define SPAM(a) printf a
#else
#define SPAM(a) (void)0
#endif
So I can do this all over my code
SPAM(("foo: %d\n", 42));
and then disable all of them by changing 1 to 0 in #if above.
But if you have variadic macro support in all compilers that you write code for, then you may go for other answers and just redefine printf. (That being said, I find it useful to distinct debugging prints from regular ones in code — using a different function name helps readability.)
Note that you also can redirect stdout to the /dev/null, but I assume that you want to get rid from runtime overhead as well.
#ifdef IGNORE_PRINTF
#define printf(fmt, ...) (0)
#endif
See also C #define macro for debug printing which discusses some important issues closely related to this.
Two options, either:
#define printf(...)
(requires C99 variadic macro parameters), you need to put it in some common header file which is never included before stdio.h, if there is one..
Or you can tell the linker to link it to something else, in GCC you would define
int wrap_printf(void) {return 0;}
and link using
--wrap printf
All that said, you should probably not be using printf for printing debug output, but rather a macro or utility function (which in turn can use printf if you'd like) which you have better control over.
Hope that helps.
If you want to avoid the potential warning that Jonathan's answer may give you and if you don't mind an empty call to printf you could also do something like
#define printf(...) printf("")
This works because C macros are not recursive. The expanded printf("") will just be left as such.
Another variant (since you are using gcc) would be something like
inline int ignore_printf(char const*, ...)
__attribute__ ((format (printf, 1, 2)));
inline int ignore_printf(char const*, ...) { return 0; }
#define printf ignore_printf
and in one compilation unit
int ignore_printf(char const*, ...)
I use to prefix the debug printf()s (not all of them) with PDEB.
For the debug builds, I compile with -DPDEB= (nothing)
For the release builds, I compile with -DPDEB="0&&" or -DPDEB="0 && "
That way, the following code (test.c):
#include <stdio.h>
void main(void) {
printf("normal print\n");
PDEB printf("debug print\n");
}
outputs:
either (in release mode):
normal print
either (in debug mode):
normal print
debug print
Ideally, one could aim for turning the PDEB into the "//" (comments mark), except that this is not possible under the standard pre-/processing chain.
Another possibility would be something like freopen("/dev/null", "w", stdout);
This doesn't exactly disable printf though -- it's roughly equivalent to running your program with stdout redirected to /dev/null, like: ./myprog > /dev/null at the shell prompt.
I included #define printf // in common header file. It will suppress all the printf.
Below simple function serves the purpose, I use the same.
int printf(const char *fmt, ...)
{
return (0)
}
Use this macro to enable or disable the printf.
//Uncomment the following line to enable the printf function.
//#define ENABLE_PRINTF
#ifdef ENABLE_PRINTF
#define DEBUG_PRINTF(f,...) printf(f,##__VA_ARGS__)
#else
#define DEBUG_PRINTF(f,...)
#endif
Then call "DEBUG_PRINTF" instead of "printf".
For example:
DEBUG_PRINTF("Hello world: %d", whateverCount);
I have used two macros for this. The first one defines the condition to print. In this simple example we print any time the parameter is not zero. More complex expressions can be used.
The second one determines, based on the first macro, to call or not printf.
If the condition can be determined by the compiler (with the right optimization settings) no code is generated.
If the condition cannot be determined at compile time then will be at run time. One of the advantages of this method is that if printf is not going to happen then the whole printf is not evaluated avoiding many conversions to string that can happen in a complex printf statement.
#define need_to_print(flag) ((flag) != 0))
#define my_printf(debug_level, ...) \
({ \
if(need_to_print(debug_level)) \
printf(__VA_ARGS__); \
})
to use it call my_printf instead of printf and add a parameter at the beginning for the print condition.
my_printf(0, "value = %d\n", vv); //this will not print
my_printf(1, "value = %d\n", vv); //this will print
my_printf(print_debug, "value = %d\n", vv); //this will print if print_debug != 0
the ( ... ) parenthesis surrounding the macro make it a single statement.
I wanna know if there is any way to know where the function currently in execution was called, this is, in what file and line.
I'm using C language, and I'm looking for something similar to __FUNCTION__, __LINE__ or __FILE__ macros.
Rename your function
void Function(param1)
{
}
to
void Function_debug(param1, char * file, char * func, unsigned long line)
{
}
Then #define a macro like this:
#define Function(param1) Function_debug(param1, __FILE__, __FUNCTION__, __LINE__)
There's nothing in C itself that would give you this information. You could either trace the information yourself (upon entry/exit) or rely on platform specific APIs to walk the call stack and determine the calling function, but not much more.
__FILE__, __LINE__ etc are preprocessor macros which can easily be expanded to the correct value at compile time. A function may get called from many possible places, so that can't be done via the preprocessor. Finding out the caller's name would be very difficult; it involves walking the stack and matching addresses to symbols.
If you can live with a small hack, this might work (untested):
/* Add a called argument to your function */
void _myFunction(char *caller, int more_args)
/* And define a macro that adds it automagically */
#define myFunction(a) _myFunction(__FUNCTION__, a)
There isn't anything that is supported in all implementations that will do what you want. I have occasionally found myself in the same situation, where I needed to track callers for a few methods and did something like the following:
#ifdef TRACKBACK
int foo(int arg1, int arg2, const char * file, int line)
{
SEND_TO_LOG("foo", file, line);
#else
int foo(int arg1, int arg2)
{
#endif
...
...
Of course, it makes for a bit of a headache at the calling end, so you'll want to do something like:
#ifdef TRACKBACK
#define TRACKING, __FILE__, __LINE__
#else
#define TRACKING
#endif
Then the call:
foo(arg1, arg2 TRACKING); //note the lack of the comma
It does the trick when all else fails.
If you need to know it at runtime, I don't think it's possible.
If you need to know it at debugtime, you can place a breakpoint on the function you want, and then, using GDB (using bt command) or Vistual Studio's debugger, inspect the current STACK TRACE.
This is actually a bit more complicated to do. Your best bet is to get a backtrace on a debugger, or find something similar to pstack for your platform. The manual way would involve traversing the call stack and using debug symbols to translate that to files and lines.
You can use logs .
#define BEGIN_FUNC(X,Y,Z) printf("Function %s Entered at line %d from file %s",X,Z,Y)
#define END_FUNC(X) printf("Function %s Exited at line %d from file %s",X,Z,Y)
foo()
{
BEGIN_FUNC(__func__,__FILE__,__LINE__);
//Your code here
END_FUNC(__func___FILE__,__LINE__);
}
OR
Use bt in gdb. I call it backtrace.
How does the following code work?
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_MSG printf
#else
#define LOG_MSG(...)
#endif
Depending on the value of ENABLE_DEBUG, LOG_MSG is either defined to be an alias for printf() or it is defined as a no-op macro. It is implied that you can change the value to 0 to disable debugging. This is a common technique for making it easy to switch between debugging builds which display lots of output and release builds which are quiet.
#define LOG_MSG printf
This makes it an alias for printf().
#define LOG_MSG(...) /* empty */
And this defines it as an empty macro. Notice that here it has a set of parentheses, which means the macro takes parameters. It has nothing afterwards which means it expands to absolutely nothing. And the ... indicates that this macro can take a varying number of arguments. This syntax is a C99 extension so it may not be available on older C compilers.
LOG_MSG("file not found\n");
The result is that a LOG_MSG() call will either print a message or do nothing depending on whether logging is enabled.
// If ENABLE_DEBUG is non-zero, a debugging printout:
printf("file not found\n");
// If ENABLE_DEBUG is zero, an empty statement:
;
For what it's worth, whoever authored this macro could've done a better job by replacing the first definition with one using the ... syntax (which he/she is clearly familiar with), printing to stderr instead of stdout:
#define LOG_MSG(...) fprintf(stderr, __VA_ARGS__)
This uses the preprocessor to change code before compilation.
If ENABLE_DEBUG is defined as 1, whenever the preprocessor sees
LOG_MSG("something happened");
It will replace it with
printf("something happened");
If it is defined as 0, or not defined it will replace it with nothing (as the other answer that has just been published says).