C11 _Generic:如何处理字符串文字?

使用C11中的_Genericfunction,您如何处理字符串文字?

例如:

 #include  #define foo(x) _Generic((x), char *: puts(x)) int main() { foo("Hello, world!"); return 0; } 

在clang上给出了这个错误:

 controlling expression type 'char [14]' not compatible with any generic association type 

char[]替换char *给了我

 error: type 'char []' in generic association incomplete 

获得这个编译的唯一方法(据我所知)是:

  1. 将字符串文字转换为适当的类型。 这很丑陋(在我看来)首先打败了_Generic
  2. 使用char[14]作为类型说明符。 你一定在开玩笑吧……

我的假设是,当传递给_Generic时,数组会衰减到指针,但显然不是。 那么,如何将_Generic与字符串文字一起使用? 那是唯一的两种选择吗?

我在Debian上使用clang 3.2。 不幸的是,它是我可以访问的唯一支持此function的编译器,因此我无法判断它是否是编译器错误。

这是一个解决方案:

 #include  #define foo(x) _Generic((0,x), char*: puts(x)) int main() { foo("Hello, world!"); return 0; } 

这编译并生成:

 $ clang tc && ./a.out Hello, world! 

它有些蹩脚,但是我没有找到任何更好的方法来使x衰减到指向char的指针,也不能以模糊方式匹配它的类型,Apple LLVM版本4.2(clang-425.0.28)(基于LLVM 3.2svn)。

根据Jens Gusted的这篇博客文章 ,GCC的行为是不同的(在GCC中,字符串显然会自动衰减到_Generic上下文中的指针)。

顺便说一下,在C中,字符串文字的类型是char数组,而不是const char数组。 在generics关联中拒绝char []作为类型名称不是编译器错误:

通用选择应具有不超过一个默认通用关联。 generics关联中的类型名称应指定除可变修改类型之外的完整对象类型。 (重点是6.5.1.1:2)

我想出了一种避免使用聪明(0,x)技巧的方法。

如果使用字符串文字,则类型为char[s] ,其中s是字符串文字的大小。

你如何获得这个大小?,使用sizeof运算符:

 #include  #define Test( x ) _Generic( ( x ) , char*: puts , \ const char*: puts , \ const char[sizeof( x )]: puts , \ char[sizeof( x )]: puts )( x ) int main(void) { char str[] = "This" ; Test( str ) ; Test( "works" ) ; char str2[10] = "!!!" ; Test( str2 ) ; return 0; } 

我尝试用clang和Pelles编译它并且它起作用了。

你仍然需要构建可变长度数组的唯一问题。

在尝试了一些之后,我找到了另一种模拟Pascal Cuoq做的方法,使用&*运算符:

 #include  #define foo(x) _Generic( ( &*(x) ), char*: puts , const char*: puts )( x ) int main() { foo("Hello, world!"); return 0; }