C11 _Generic:如何处理字符串文字?
使用C11中的_Generic
function,您如何处理字符串文字?
例如:
#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
获得这个编译的唯一方法(据我所知)是:
- 将字符串文字转换为适当的类型。 这很丑陋(在我看来)首先打败了
_Generic
。 - 使用
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; }