我尝试实现可以采用任何数据类型并处理它的_Generic宏,这个示例工作正常,但是使用2个Generic宏,我怎样才能使用一个带有char * int和double的Generic来实现它?
#include <stdio.h>
#include <stdlib.h>
#define puts(x) _Generic((x), \
char*: _puts((void*) x, "str"), \
int: _puts((void*) x, "int") \
)
#define putsd(x) _Generic((x),\
double: _puts((void*)to_s(x), "float") \
)
char*
to_s(double x)
{
char* str = (char *)malloc(1502);
sprintf(str, "%lf", x);
free(str);
return str;
}
void _puts(void* d, const char* type)
{
if (strcmp(type, "int") == 0){
printf("%d\n", d);
} else if (strcmp(type, "float") == 0){
double res;
sscanf(d, "%lf", &res);
printf("%lf\n", res);
} else {
printf("%s\n", d);
}
}
int main(void) {
puts("String");
puts(1230);
putsd(13.37);
return 0;
}
此外,当我尝试跟随时,我得到错误&#34;&#39; to_s&#39;的参数1的不兼容类型放(&#34;字符串&#34); :
#include <stdio.h>
#include <stdlib.h>
#define puts(x) \
_Generic((x), \
char*: _puts((void*) x, "str"), \
int: _puts((void*) x, "int"), \
double : _puts((void *)to_s(x), "float") \
)
char *to_s(double x) {
char *str = (char *)malloc(1502);
sprintf(str, "%lf", x);
free(str);
return str;
}
void _puts(void *d, const char *type) {
if (strcmp(type, "int") == 0) {
printf("%d\n", d);
} else if (type == "float") {
double res;
sscanf(d, "%lf", &res);
printf("%lf\n", res);
} else {
printf("%s\n", d);
}
}
int main(void) {
puts("String");
puts(1230);
puts(13.37);
return 0;
}
答案 0 :(得分:2)
您无法将字符串与==
更改
if (type == "int") {
与
if (strcmp(type, "int") == 0) {
float
...
另一方面,你不能传递像1230
或13.39
这样的文字的地址,使用中间指针:
int i = 1230;
int *pi = &i;
puts(pi);
然后在你的通用宏中:
#define puts(x) \
_Generic((x), \
char*: _puts((x), "str"), \
int *: _puts((x), "int"), \
double *: _puts((x), "float") \
)
GLib使用一些丑陋的技巧将文字(转换为long
)作为指针传递,但这不可移植:Type Conversion Macros
另外,请注意puts
是标准库中函数的名称,覆盖此名称不是一个好主意。
使用复合文字修正代码以传递指针:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Puts(x) \
_Generic((x), \
char *: _Puts((x), "str"), \
int *: _Puts((x), "int"), \
double *: _Puts((x), "float") \
)
static void _Puts(void *d, const char *type)
{
if (strcmp(type, "int") == 0) {
printf("%d\n", *(int *)d);
} else
if (strcmp(type, "float") == 0) {
printf("%f\n", *(double *)d);
} else {
printf("%s\n", (char *)d);
}
}
int main(void)
{
Puts("String");
Puts((int []){1230});
Puts((double []) {13.37});
return 0;
}
答案 1 :(得分:0)
你错过了泛型的全部要点,你创建了一个完全按照通用做的函数(又名。_puts()
。你应该直接在你的泛型中使用正确的函数,加上to_s()
free { {1}} ...然后你使用它!调用未定义的行为。并且不要使用stdlib的保留函数名str
一个很好的例子是here
puts()