Home > Software design >  How to identify whether a variable exists inside a C function for logging?
How to identify whether a variable exists inside a C function for logging?

Time:07-05

How to check if a variable exists in some function? The goal is to define a logging function that will print the message along with some variable that may or may not exist.

I've been trying to achieve this with macros but to no avail :(

// if bar exists, print bar_id and the log.
#if EXIST(bar)
#define Log LogWithBar
#endif

void LogWithBar() 
{
    // print as with Log and add bar.data value
}

void func1(foo bar, ...)
{
   bar.data = 111
    ...
    Log("First")
//  First 111 
}

void func2( ...) // no bar
{
    ...
    Log("First")
//  First 
}

The detailed use-case is that i have a large code with hundreds of functions, many of them have some common struct but many others do not. I'd like to have the logging function to print some value from this struct whenever it exists (along with the actual log string), and print just the log string if it does not exist.

CodePudding user response:

#include <stdio.h>


//  Define a "bar" with external scope with a type we can distinguish.
const struct DummyType { char dummy; } bar;


/*  If "bar" has the dummy type, there is no local "bar" hiding it, so do
    nothing.  Otherwise, there is a local "bar" hiding the external one, so
    do something.
*/
#define Log(x)                      \
    _Generic(bar,                   \
        struct DummyType: (void) 0, \
        default: puts(x)            \
        )


//  This function has no "bar", so nothing will be logged.
void func0(void)
{
    Log("func0");
}


//  This function has a "bar", so its message will be logged.
void func1(int bar)
{
    Log("func1");
}


int main(void)
{
    func0();
    func1(0);
}

In versions of C prior to the introduction of _Generic, you can test the address:

//  Define a "bar" with external scope to serve as a sentinel.
const char bar;
const void *pbar = &bar;


/*  If the address of bar is pbar, there is no local "bar" hiding it, so do
    nothing.  Otherwise, there is a local "bar" hiding the external one, so
    do something.
*/
#define Log(x)  \
    do if ((const void *) &bar != pbar) puts(x); while (0)
  • Related