1

我有一个带有联合和枚举的结构。我制作了一个宏,它输出结构的复合文字,根据传递给宏的类型设置联合的种类和数据使用_Generic。

示例代码:

#include <stdio.h>

struct mystruct {
    enum { K_NUM, K_STR } kind;
    union { int num; char * str; };
};

#define MYSTRUCT(X) _Generic((X), \
    int: (struct mystruct){K_NUM, .num=X}, \
    char *: (struct mystruct){K_STR, .str=X} \
)

void print_mystruct(struct mystruct s) {
    switch (s.kind) {
    case K_NUM: printf("mystruct (num): %d\n", s.num); break;
    case K_STR: printf("mystruct (str): %s\n", s.str); break;
    }
}

int main() {
    print_mystruct(MYSTRUCT(2));
    print_mystruct(MYSTRUCT("test"));
}

它确实使用 gcc 编译,然后正确运行它输出:

mystruct (num): 2
mystruct (str): test

但是我得到了所有这些编译警告:

c.c: In function 'main':
c.c:21:26: warning: initialization of 'char *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
   21 |  print_mystruct(MYSTRUCT(2));
      |                          ^
c.c:10:40: note: in definition of macro 'MYSTRUCT'
   10 |  char *: (struct mystruct){K_STR, .str=X} \
      |                                        ^
c.c:21:26: note: (near initialization for '(anonymous).<anonymous>.str')
   21 |  print_mystruct(MYSTRUCT(2));
      |                          ^
c.c:10:40: note: in definition of macro 'MYSTRUCT'
   10 |  char *: (struct mystruct){K_STR, .str=X} \
      |                                        ^
c.c:22:26: warning: initialization of 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion]
   22 |  print_mystruct(MYSTRUCT("test"));
      |                          ^~~~~~
c.c:9:37: note: in definition of macro 'MYSTRUCT'
    9 |  int: (struct mystruct){K_NUM, .num=X}, \
      |                                     ^
c.c:22:26: note: (near initialization for '(anonymous).<anonymous>.num')
   22 |  print_mystruct(MYSTRUCT("test"));
      |                          ^~~~~~
c.c:9:37: note: in definition of macro 'MYSTRUCT'
    9 |  int: (struct mystruct){K_NUM, .num=X}, \
      |                                     ^

我尝试在复合文字中进行强制转换,如下所示:

int: (struct mystruct){K_NUM, .num=(int)X}, \
char *: (struct mystruct){K_STR, .str=(char *)X} \

但我收到不同的警告:

c.c: In function 'main':
c.c:9:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    9 |  int: (struct mystruct){K_NUM, .num=(int)X}, \
      |                                     ^
c.c:22:17: note: in expansion of macro 'MYSTRUCT'
   22 |  print_mystruct(MYSTRUCT("test"));
      |                 ^~~~~~~~
4

1 回答 1

2

这是因为每次调用宏时,所有X找到宏参数的情况都会被展开。所以当你通过时2,你会得到

_Generic(2, int: (struct mystruct){K_NUM, .num=2}, char *: (struct mystruct){K_STR, .str=2}

即使char*没有执行这个案例,它仍然被编译并且将一个整数分配给一个字符串.str=2是无效的 C.

考虑完全采用不同的方法。例如,将宏参数保留在 _Generic 列表之外。你甚至需要枚举,因为类型在编译时是已知的?

#include <stdio.h>

void print_int (int x) { printf("%d\n", x); }
void print_str (const char* x) { puts(x); }

#define print(x) _Generic((x), \
  int:    print_int,           \
  char*:  print_str ) (x)

int main(void) 
{
  print(2);
  print("test");
}
于 2020-04-08T11:55:40.803 回答