将零参数函数添加到 _Generic 宏
Add zero arguments function to _Generic macro
我正在尝试在 C11 中使用 _Generic 宏生成重载函数,但我已停止支持零参数函数,例如:
#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;
}
现在正在编译 运行:
printf("%s",msg("hello!"));
没有任何问题,但是:
printf("%s",msg());
抛出错误:
main.c:7:17: error: expected expression
printf("%s",msg());
我正在使用:
clang --version
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
GCC 抛出:
main.c:7:5: warning: implicit declaration of function ‘_Generic’
所以我明白 _Generic 不支持这个版本的 gcc:
gcc --version
gcc (Gentoo 4.8.3 p1.1, pie-0.5.9) 4.8.3
我的问题是否可以解决,或者我只是高估了 _Generic 的功能,或者我只需要升级我的编译器以正确使用此选项?
您的问题与_Generics 没有直接关系。您只是用一个参数定义了宏 #define msg(_1)
,因此您必须传递一个参数。
如果不依赖编译器扩展,则不能将零个或多个参数传递给 _Generic 宏。您必须在零个或一个参数之间进行选择,如图所示 或者 1 个或多个。
这是我对任何宏组合的解决方案,但它涉及一个伪参数。您可以定义自己的类型,用作空宏的指示器
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)
然后调用它:
msg( msg_empty ) ;
这将调用 msg_none 函数。
C 具有可变参数宏,可以接收零个或多个参数
#define msg(...) _Generic((__VA_ARGS__+0), char*: msg_string, default: msg_none)(__VA_ARGS__)
此处 +0
还确保为您的字符串参数执行数组到指针的转换,这似乎是您假设的。
后者很重要,因为如果选择表达式是数组,gcc 和 clang 目前的行为不同。
编辑: 如果有人传入 char const*
,您可能还希望您的宏起作用,因此您也应该添加这种情况。
#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;
}
我正在尝试在 C11 中使用 _Generic 宏生成重载函数,但我已停止支持零参数函数,例如:
#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;
}
现在正在编译 运行:
printf("%s",msg("hello!"));
没有任何问题,但是:
printf("%s",msg());
抛出错误:
main.c:7:17: error: expected expression
printf("%s",msg());
我正在使用:
clang --version
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
GCC 抛出:
main.c:7:5: warning: implicit declaration of function ‘_Generic’
所以我明白 _Generic 不支持这个版本的 gcc:
gcc --version
gcc (Gentoo 4.8.3 p1.1, pie-0.5.9) 4.8.3
我的问题是否可以解决,或者我只是高估了 _Generic 的功能,或者我只需要升级我的编译器以正确使用此选项?
您的问题与_Generics 没有直接关系。您只是用一个参数定义了宏 #define msg(_1)
,因此您必须传递一个参数。
如果不依赖编译器扩展,则不能将零个或多个参数传递给 _Generic 宏。您必须在零个或一个参数之间进行选择,如图所示
这是我对任何宏组合的解决方案,但它涉及一个伪参数。您可以定义自己的类型,用作空宏的指示器
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)
然后调用它:
msg( msg_empty ) ;
这将调用 msg_none 函数。
C 具有可变参数宏,可以接收零个或多个参数
#define msg(...) _Generic((__VA_ARGS__+0), char*: msg_string, default: msg_none)(__VA_ARGS__)
此处 +0
还确保为您的字符串参数执行数组到指针的转换,这似乎是您假设的。
后者很重要,因为如果选择表达式是数组,gcc 和 clang 目前的行为不同。
编辑: 如果有人传入 char const*
,您可能还希望您的宏起作用,因此您也应该添加这种情况。
#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;
}