我试图实现一个可以接受任何数据类型并处理它的泛型宏,这个示例工作得很好,但是对于两个泛型宏,我如何使用一个带有char*int和double的泛型来实现它?

  #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;
  }

另外,当我尝试follows时,我得到一个错误“to_s”puts(“String”)的参数1的不兼容类型:
  #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;
  }

最佳答案

不能将字符串与==进行比较
改变

if (type == "int") {

具有
if (strcmp(type, "int") == 0) {

float相同。。。
另一方面,不能传递像123013.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使用一些丑陋的技巧将文本(casting tolong)作为指针传递,但这不是可移植的: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;
}

关于c - 具有void *指针的_Generic宏不带双引号?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49829970/

10-14 16:26
查看更多