Add null argument function to _Generic macro

I am trying to create overloaded functions using the _Generic macro in C11, and I settled on supporting functions of null arguments, for example:

#define msg(_1) _Generic((_1), char*: msg_string, default: msg_none)(_1) char* msg_none(void){ return moo_string("Have a nice day!"); } char* msg_string(char* message){ int msglen = strlen(message); char* result = malloc(msglen + 3); sprintf(result, "<%s>\n", message); return result; } 

Now compile and run:

 printf("%s",msg("hello!")); 

goes without problems, but:

 printf("%s",msg()); 

causes an error:

 main.c:7:17: error: expected expression printf("%s",msg()); 

I use:

  clang --version clang version 3.5.0 (tags/RELEASE_350/final) Target: x86_64-pc-linux-gnu Thread model: posix 

GCC throws:

 main.c:7:5: warning: implicit declaration of function '_Generic' 

so I understand that _Generic is not supported by this version of gcc:

 gcc --version gcc (Gentoo 4.8.3 p1.1, pie-0.5.9) 4.8.3 

Is my problem even solvable, or am I just overestimating the capabilities of _Generic, or do I just need to update my compilers to use these options correctly?

+7
c gcc macros c11 clang
source share
3 answers

C has variable macros that can take zero or more arguments

 #define msg(...) _Generic((__VA_ARGS__+0), char*: msg_string, default: msg_none)(__VA_ARGS__) 

here +0 additionally converts the array to a string pointer for your string argument, which you are supposed to assume.

The latter is important because gcc and clang currently differ in behavior if the select expression is an array.

Edit: You probably also want your macro to work if someone passed in char const* , so you should also add this case.

+3
source share

Your problem is not directly related to _Generics. You just defined the #define msg(_1) macro with an argument, so you need to pass an argument.

Unless you rely on compiler extensions, you cannot pass zero or more arguments to the _Generic macro. You will have to choose between zero or one argument, as shown here or, 1 or more.

This is my solution for any macro, but it includes a dummy argument. You can define your own type that will serve as an indicator for the emtpy macro.

 typedef struct { int unused ; } emtpy ; const empty msg_empty = { 0 } ; char* msg_none(empty e) { ( void )e ; return moo_string("Have a nice day!"); } #define msg(_1) _Generic((_1), char*: msg_string, empty : msg_none)(_1) 

And then name it with:

 msg( msg_empty ) ; 

The msg_none function will be called.

+2
source share
 #include <stdio.h> #include <stdlib.h> #include <string.h> #define dummy void #define ARGS_AUX(_0, VAR, ...) VAR #define ARGS(...) ARGS_AUX(dummy, ##__VA_ARGS__, NULL) //gnu extensions #define MSG(var) (_Generic(var, char*: msg_string(var), default: msg_none())) #define msg(...) MSG(ARGS(__VA_ARGS__)) //MSG(NULL) when no argument char *moo_string(const char *s){ return (char*)s; } char* msg_none(void){ return moo_string("Have a nice day!"); } char* msg_string(char* message){ int msglen = strlen(message); char* result = malloc(msglen + 4); sprintf(result, "<%s>\n", message); return result; } int main(void){ printf("%s\n", msg());//Have a nice day! printf("%s\n", msg((char*)"hello!"));//<hello!>, type is char[7] when no cast return 0; } 
0
source share

All Articles