请注意标准中的示例§6.5.1.1 通用选择 http://port70.net/%7Ensz/c/c11/n1570.html#6.5.1.1 is:
5 示例 cbrt 类型通用宏可以按如下方式实现:
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
请注意函数调用的括号所在的位置 - 在_Generic(…)
通用选择的一部分。
将其调整为您的代码:
#include <stdio.h>
#define FOOBAR(x) _Generic((x), \
int *: foo, \
long *: bar \
)(x)
static void foo(int *x)
{
printf("foo (%d)\n", *x);
}
static void bar(long *y)
{
printf("bar (%ld)\n", *y);
}
int main(void)
{
int a = 1111;
long b = 2222;
FOOBAR(&a);
FOOBAR(&b);
return 0;
}
这可以使用 GCC 10.2.0 set fussy 干净地编译(源文件gs31.c
):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -fno-common -c gs31.c
$
代码在外部发生变化FOOBAR
宏避免我的标准编译选项请求的编译警告。
代码的 C 预处理器的输出是:
int main() {
int a = 1111;
long b = 2222;
_Generic((&a), int *: foo(&a), long *: bar(&a) );
_Generic((&b), int *: foo(&b), long *: bar(&b) );
}
和....相比:
int main(void)
{
int a = 1111;
long b = 2222;
_Generic((&a), int *: foo, long *: bar )(&a);
_Generic((&b), int *: foo, long *: bar )(&b);
}
区别在于您的代码调用foo()
with a long *
(aka &b
) and bar()
与int *
(aka &a
),这就是(正确地)触发警告的原因。