C11 _通用用法

前端之家收集整理的这篇文章主要介绍了C11 _通用用法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图学习如何使用“新”C11通用表达式,但我碰到了一堵墙.

请考虑以下代码

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. #define test(X,Y,c) \
  5. _Generic((X),\
  6. double: _Generic((Y),\
  7. double * : test_double,\
  8. default: test_double \
  9. ),\
  10. int: _Generic((Y),\
  11. int * : test_int,\
  12. default: test_int \
  13. ) \
  14. ) (X,c)
  15.  
  16.  
  17. int test_double(double a,double *b,int c);
  18. int test_int(int a,int *b,int c);
  19.  
  20. int test_double(double a,int c) { return 1; }
  21. int test_int(int a,int c) { return 2; }
  22.  
  23. int main()
  24. {
  25. double *t = malloc(sizeof(double));
  26. int *s = malloc(sizeof(int));
  27. int a1 = test(3.4,t,1);
  28. int i = 3;
  29. int a2 = test(i,s,1);
  30. printf("%d\t",a1);
  31. printf("%d\n",a2);
  32. return 0;
  33. }

这一切都完美有效,但我不明白为什么“_Generic((Y),…”中的默认情况是必要的,而我可以在“_Generic((X),…”的末尾省略它)没有后果.

事实上,如果我删除这两个默认值,我会得到一个错误(gcc 5.4.0)说“类型’double *’的选择器与任何关联都不兼容”而宏扩展“int a1 = test(3.4,1 );”宏扩展测试(i,1)与“int *”相同

“默认”真的有必要还是我错过了什么?
在第一种情况下,为什么它应该是?如果我只有test_double和test_int可以调用,为什么我应该为一些永远不会编译的东西放置一个默认情况?

解决方法

TL; DR

选择在编译时发生,但这并不意味着丢弃其他(未选择)代码.它仍然必须有效,这意味着……

If default is not used and none of the type-names are compatible with the type of the controlling expression,the program will not compile.

(Source)

这是一个令人惊讶的:

没有“第一个Y”的默认情况:

  1. #define test(X,\
  2. double * : test_double \
  3. ),\
  4. default: test_default \
  5. ) \
  6. ) (X,c)

我收到了这个错误

prog.c:6:30: error: ‘_Generic’ selector of type ‘int *’ is not compatible with any association

请注意,它抱怨int *不兼容!为什么?
那么让我们来看看报告的行:

  1. int a2 = test(i,1);

X的类型为int,类型为int *的Y.

现在是重要的部分:扩展无条件地发生.因此,即使X是int类型,X的第一个关联(当它是double类型时)必须是一个格式良好的程序.因此,如果Y是一个int *,则必须形成以下内容

  1. _Generic((Y),\
  2. double * : test_double \
  3. ),\

因为int *不是double *,所以事情在这里打破.

我只是在查看标准(实际上是N1570)并且找不到任何实际指定这种行为的东西.我想在这种情况下可以报告一个缺陷,标准对此太过模糊.我现在正试图这样做.

猜你在找的C&C++相关文章