C11 _Generic() 表达式在嵌套时失败
C11 _Generic() expression failing if being nested
我试图找出嵌套 _Generic()
表达式对我来说失败的原因。如果我不嵌套它们,它们工作正常。
当然,我在一个较长的程序中遇到过这种情况,但我将其总结为一个最小的工作示例,它触发的错误与在较大的程序中完全相同。
我试着反复检查代码,但没有找到确凿的证据...问题的原因是什么?
#include <stdio.h>
typedef struct sta
{
char a;
}ta;
typedef struct stb
{
short b;
}tb;
typedef struct stc
{
int c;
}tc;
#define MAGICNUMBER(X) _Generic((X), \
ta: 1, \
tb: 2, \
tc: 3 \
)
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
ta: 1 \
)
#define NESTEDMAGICNUMBER2(X) _Generic((X), \
tb: 2, \
default: NESTEDMAGICNUMBER3(X) \
)
#define NESTEDMAGICNUMBER(X) _Generic((X), \
tc: 3, \
default: NESTEDMAGICNUMBER2(X) \
)
int main(int argc, char *argv[])
{
ta a;
tb b;
tc c;
printf("direct macro: ta has # %d\n",MAGICNUMBER(a));
printf("direct macro: tb has # %d\n",MAGICNUMBER(b));
printf("direct macro: tc has # %d\n",MAGICNUMBER(c));
printf("nested macro: ta has # %d\n",NESTEDMAGICNUMBER(a)); /* Compile-time error why? */
printf("nested macro: tb has # %d\n",NESTEDMAGICNUMBER(b)); /* Compile-time error why? */
printf("nested macro: tc has # %d\n",NESTEDMAGICNUMBER(c)); /* Compile-time error why? */
return 0;
}
编译时,我得到这个:
cc -o testgeneric testgeneric.c
testgeneric.c:49:39: error: controlling expression type 'tb' (aka 'struct stb') not compatible with any generic association type
printf("nested macro: tb has # %d\n",NESTEDMAGICNUMBER(b)); /* Compile-time error why? */
^~~~~~~~~~~~~~~~~~~~
testgeneric.c:36:10: note: expanded from macro 'NESTEDMAGICNUMBER'
default: NESTEDMAGICNUMBER2(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:31:10: note: expanded from macro 'NESTEDMAGICNUMBER2'
default: NESTEDMAGICNUMBER3(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:25:40: note: expanded from macro 'NESTEDMAGICNUMBER3'
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
^~~
testgeneric.c:50:39: error: controlling expression type 'tc' (aka 'struct stc') not compatible with any generic association type
printf("nested macro: tc has # %d\n",NESTEDMAGICNUMBER(c)); /* Compile-time error why? */
^~~~~~~~~~~~~~~~~~~~
testgeneric.c:36:10: note: expanded from macro 'NESTEDMAGICNUMBER'
default: NESTEDMAGICNUMBER2(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:31:10: note: expanded from macro 'NESTEDMAGICNUMBER2'
default: NESTEDMAGICNUMBER3(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:25:40: note: expanded from macro 'NESTEDMAGICNUMBER3'
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
^~~
2 errors generated.
为什么嵌套版本失败,而非嵌套版本正常?
谢谢!
在 _Generic
表达式中,传入类型 必须 匹配给定类型之一或具有 default
部分。
让我们看一下预处理器输出,看看发生了什么:
printf("direct macro: ta has # %d\n",_Generic((a), ta: 1, tb: 2, tc: 3 ));
printf("direct macro: tb has # %d\n",_Generic((b), ta: 1, tb: 2, tc: 3 ));
printf("direct macro: tc has # %d\n",_Generic((c), ta: 1, tb: 2, tc: 3 ));
printf("nested macro: ta has # %d\n",_Generic((a), tc: 3, default: _Generic((a), tb: 2, default: _Generic((a), ta: 1 ) ) ));
printf("nested macro: tb has # %d\n",_Generic((b), tc: 3, default: _Generic((b), tb: 2, default: _Generic((b), ta: 1 ) ) ));
printf("nested macro: tc has # %d\n",_Generic((c), tc: 3, default: _Generic((c), tb: 2, default: _Generic((c), ta: 1 ) ) ));
前三行使用非嵌套宏。在每一种情况下,传入的类型都匹配 3 种情况之一。
现在让我们看一下嵌套的情况,特别是第二个:
_Generic((b), tc: 3, default: _Generic((b), tb: 2, default: _Generic((b), ta: 1 ) ) ))
在最后一个案例中:_Generic((b), ta: 1 )
,b
的类型不是 ta
并且没有 default
案例,所以这是编译器抱怨的地方。请注意,所有 _Generic
表达式必须有效,即使它们最终不是被评估的情况。
您可以通过给最里面的宏一个 default
大小写来解决这个问题:
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
ta: 1, \
default: 0 \
)
Why does the nested version fail, while the non-nested version works fine?
考虑NESTEDMAGICNUMBER(b))
的扩展:
_Generic((b), tc: 3, default: _Generic((b), tb: 2, default: _Generic((b), ta: 1 ) ) )
编译器拒绝此表达式,因为子表达式 _Generic((b), ta: 1 )
由于没有 b
类型的大小写(tb
、a.k.a)而无效。 struct stb
)。这不是将要选择的通用替代项的一部分这一事实无关紧要——程序源代码中的每个表达式和子表达式都必须有效,无论它是否有任何效果。您可以通过添加 default
替代 NESTEDMAGICNUMBER3
:
来解决问题
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
ta: 1, \
default: 0 \
)
我试图找出嵌套 _Generic()
表达式对我来说失败的原因。如果我不嵌套它们,它们工作正常。
当然,我在一个较长的程序中遇到过这种情况,但我将其总结为一个最小的工作示例,它触发的错误与在较大的程序中完全相同。
我试着反复检查代码,但没有找到确凿的证据...问题的原因是什么?
#include <stdio.h>
typedef struct sta
{
char a;
}ta;
typedef struct stb
{
short b;
}tb;
typedef struct stc
{
int c;
}tc;
#define MAGICNUMBER(X) _Generic((X), \
ta: 1, \
tb: 2, \
tc: 3 \
)
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
ta: 1 \
)
#define NESTEDMAGICNUMBER2(X) _Generic((X), \
tb: 2, \
default: NESTEDMAGICNUMBER3(X) \
)
#define NESTEDMAGICNUMBER(X) _Generic((X), \
tc: 3, \
default: NESTEDMAGICNUMBER2(X) \
)
int main(int argc, char *argv[])
{
ta a;
tb b;
tc c;
printf("direct macro: ta has # %d\n",MAGICNUMBER(a));
printf("direct macro: tb has # %d\n",MAGICNUMBER(b));
printf("direct macro: tc has # %d\n",MAGICNUMBER(c));
printf("nested macro: ta has # %d\n",NESTEDMAGICNUMBER(a)); /* Compile-time error why? */
printf("nested macro: tb has # %d\n",NESTEDMAGICNUMBER(b)); /* Compile-time error why? */
printf("nested macro: tc has # %d\n",NESTEDMAGICNUMBER(c)); /* Compile-time error why? */
return 0;
}
编译时,我得到这个:
cc -o testgeneric testgeneric.c
testgeneric.c:49:39: error: controlling expression type 'tb' (aka 'struct stb') not compatible with any generic association type
printf("nested macro: tb has # %d\n",NESTEDMAGICNUMBER(b)); /* Compile-time error why? */
^~~~~~~~~~~~~~~~~~~~
testgeneric.c:36:10: note: expanded from macro 'NESTEDMAGICNUMBER'
default: NESTEDMAGICNUMBER2(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:31:10: note: expanded from macro 'NESTEDMAGICNUMBER2'
default: NESTEDMAGICNUMBER3(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:25:40: note: expanded from macro 'NESTEDMAGICNUMBER3'
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
^~~
testgeneric.c:50:39: error: controlling expression type 'tc' (aka 'struct stc') not compatible with any generic association type
printf("nested macro: tc has # %d\n",NESTEDMAGICNUMBER(c)); /* Compile-time error why? */
^~~~~~~~~~~~~~~~~~~~
testgeneric.c:36:10: note: expanded from macro 'NESTEDMAGICNUMBER'
default: NESTEDMAGICNUMBER2(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:31:10: note: expanded from macro 'NESTEDMAGICNUMBER2'
default: NESTEDMAGICNUMBER3(X) \
^~~~~~~~~~~~~~~~~~~~~
testgeneric.c:25:40: note: expanded from macro 'NESTEDMAGICNUMBER3'
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
^~~
2 errors generated.
为什么嵌套版本失败,而非嵌套版本正常?
谢谢!
在 _Generic
表达式中,传入类型 必须 匹配给定类型之一或具有 default
部分。
让我们看一下预处理器输出,看看发生了什么:
printf("direct macro: ta has # %d\n",_Generic((a), ta: 1, tb: 2, tc: 3 ));
printf("direct macro: tb has # %d\n",_Generic((b), ta: 1, tb: 2, tc: 3 ));
printf("direct macro: tc has # %d\n",_Generic((c), ta: 1, tb: 2, tc: 3 ));
printf("nested macro: ta has # %d\n",_Generic((a), tc: 3, default: _Generic((a), tb: 2, default: _Generic((a), ta: 1 ) ) ));
printf("nested macro: tb has # %d\n",_Generic((b), tc: 3, default: _Generic((b), tb: 2, default: _Generic((b), ta: 1 ) ) ));
printf("nested macro: tc has # %d\n",_Generic((c), tc: 3, default: _Generic((c), tb: 2, default: _Generic((c), ta: 1 ) ) ));
前三行使用非嵌套宏。在每一种情况下,传入的类型都匹配 3 种情况之一。
现在让我们看一下嵌套的情况,特别是第二个:
_Generic((b), tc: 3, default: _Generic((b), tb: 2, default: _Generic((b), ta: 1 ) ) ))
在最后一个案例中:_Generic((b), ta: 1 )
,b
的类型不是 ta
并且没有 default
案例,所以这是编译器抱怨的地方。请注意,所有 _Generic
表达式必须有效,即使它们最终不是被评估的情况。
您可以通过给最里面的宏一个 default
大小写来解决这个问题:
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
ta: 1, \
default: 0 \
)
Why does the nested version fail, while the non-nested version works fine?
考虑NESTEDMAGICNUMBER(b))
的扩展:
_Generic((b), tc: 3, default: _Generic((b), tb: 2, default: _Generic((b), ta: 1 ) ) )
编译器拒绝此表达式,因为子表达式 _Generic((b), ta: 1 )
由于没有 b
类型的大小写(tb
、a.k.a)而无效。 struct stb
)。这不是将要选择的通用替代项的一部分这一事实无关紧要——程序源代码中的每个表达式和子表达式都必须有效,无论它是否有任何效果。您可以通过添加 default
替代 NESTEDMAGICNUMBER3
:
#define NESTEDMAGICNUMBER3(X) _Generic((X), \
ta: 1, \
default: 0 \
)