_Generic从C11处理,我写了一个简单的例子:
#include <stdio.h>
#define swap(a, b) _Generic((a), \
int*: swap_int(a, b), \
float*: swap_float(a, b) \
)
void swap_int(int* a, int* b) {
int tmp = *a; *a = *b; *b = tmp;
}
void swap_float(float* a, float* b) {
float tmp = *a; *a = *b; *b = tmp;
}
int main(int argc, char const *argv[]) {
int a = 10, b = 40;
float c = 3.14, d = 2.71;
printf("a = %d b = %d\n", a, b);
swap(&a, &b);
printf("a = %d b = %d\n\n", a, b);
printf("c = %.2f d = %.2f\n", c, d);
swap(&c, &d);
printf("c = %.2f d = %.2f\n", c, d);
}
程序运行正常,但编译时出现类型不匹配警告:
temp.c: In function 'main':
temp.c:819:10: warning: passing argument 1 of 'swap_float' from incompatible pointer type [-Wincompatible-pointer-types]
swap(&a, &b);
^
temp.c:799:24: note: in definition of macro 'swap'
float*: swap_float(a, b) \
^
temp.c:808:6: note: expected 'float *' but argument is of type 'int *'
void swap_float(float* a, float* b) {
^~~~~~~~~~
temp.c:819:14: warning: passing argument 2 of 'swap_float' from incompatible pointer type [-Wincompatible-pointer-types]
swap(&a, &b);
^
temp.c:799:27: note: in definition of macro 'swap'
float*: swap_float(a, b) \
^
temp.c:808:6: note: expected 'float *' but argument is of type 'int *'
void swap_float(float* a, float* b) {
^~~~~~~~~~
temp.c:823:10: warning: passing argument 1 of 'swap_int' from incompatible pointer type [-Wincompatible-pointer-types]
swap(&c, &d);
^
temp.c:798:20: note: in definition of macro 'swap'
int*: swap_int(a, b), \
^
temp.c:802:6: note: expected 'int *' but argument is of type 'float *'
void swap_int(int* a, int* b) {
^~~~~~~~
temp.c:823:14: warning: passing argument 2 of 'swap_int' from incompatible pointer type [-Wincompatible-pointer-types]
swap(&c, &d);
^
temp.c:798:23: note: in definition of macro 'swap'
int*: swap_int(a, b), \
^
temp.c:802:6: note: expected 'int *' but argument is of type 'float *'
void swap_int(int* a, int* b) {
如何删除它们?
编译器:gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
在这种情况下,您只需稍微更改宏的语法:
也许有更好的解决方案。我
_Generic还没有深挖...更新: 以下是我的观点和思考。
这实际上是标准的重写示例。我或多或少可以回答“它是如何工作的”这个问题:
_Generic表达式实际上“有一个值”指向相应函数的指针,然后用参数а和b. 但是这种方法有局限性:例如,如果swap_int它是一个宏或者如果其中一个函数有其他元素,它将不起作用。考虑到这一点,原始版本更加灵活。推测一下,我也可以解释为什么 gcc 实现在处理它时会出现警告:实际上,表达式存在于文本中,并且在扩展之前检查指针的正确性
_Generic。但是,我在代码中没有看到任何犯罪行为,恕我直言,它们是误报,因此值得在知识渊博的人居住的地方讨论这个示例,例如在 gcc 邮件列表或 bugzilla 中。此外,为了抑制警告,您可以使用 hack:将指针显式转换为所需类型或
(void*).