Home > database >  c _Generic and macro funtion
c _Generic and macro funtion

Time:05-04

I'm writing DEBUG_MSG for print debug messages

#define DEBUG_MSG(msg_str) _DEBUG_MSG_GENERIC(msg_str)

The _DEBUG_MSG_GENERIC is because I'd like to:

  • Show int message when a input parameter is int
  • Show char* message when a input parameter is char*

and its implement:

#define _DEBUG_MSG_GENERIC(strs) \
  _Generic( (strs), \
             int: _DEBUG_MSG_INT, \
             default: _DEBUG_MSG_STR \
          )(strs)

Now I'd like to implement _DEBUG_MSG_INT and _DEBUG_MSG_STR with Macro function and printf :

#define _DEBUG_MSG_INT(val) printf("%d\n", val);
#define _DEBUG_MSG_STR(str) printf("%s\n", str);

But I got error message is:

main.c:14:30: error: ‘_DEBUG_MSG_INT’ undeclared (first use in this function); did you mean ‘DEBUG_MSG’?
   14 |                         int: _DEBUG_MSG_INT, \
      |                              ^~~~~~~~~~~~~~

How do I solve it?

Does _generic only support function(pointer to function) and not support macro function?

Full Code

#include <stdio.h>

#define DEBUG_MSG(msg_str) _DEBUG_MSG_GENERIC(msg_str)
#define _DEBUG_MSG_GENERIC(strs) \
            _Generic( (strs), \
                        int: _DEBUG_MSG_INT, \
                      default: _DEBUG_MSG_STR \
                    )(strs)
#define _DEBUG_MSG_INT(val) printf("%d\n", val)
#define _DEBUG_MSG_STR(str) printf("%s\n", str)

int main()
{
    DEBUG_MSG("str");
    DEBUG_MSG(5);
}

CodePudding user response:

I believe your issue is because the preprocessor only makes one pass of the source code, so the printf's don't get substituted.

A quick solution would be to define _DEBUG_MSG_INT(val) and _DEBUG_MSG_STR(str) as real functions like so:

void _DEBUG_MSG_INT(int val) {
    printf("%d\n", val);
}
void _DEBUG_MSG_STR(char * str) {
    printf("%s\n", str);
}

The compiler will optimise out the extra function call overhead and will behave as if you called printf directly.

CodePudding user response:

The problem is that both _DEBUG_MSG_INT and _DEBUG_MSG_STR are function-like macros thus they are only expanded if they are followed by ().

Note that macro expansion takes place before actual C compilation thus _Generic is nothing more than a common identifier at preprocessor stage.

I suggest using _Generic not for selection of the function pointer but rather for a formatting specifier to be used in printf(). Try:

#define _DEBUG_MSG_GENERIC(arg) printf( _DEBUG_MSG_FMTSPEC(arg), arg)
#define _DEBUG_MSG_FMTSPEC(arg) \
  _Generic( (arg), int: "%d\n", default: "%s\n")
  • Related