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

Mic*_*son 25 c clang c11

使用_GenericC11中的功能,您如何处理字符串文字?

例如:

#include <stdio.h>
#define foo(x) _Generic((x), char *: puts(x))

int main()
{
    foo("Hello, world!");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在clang上给出了这个错误:

controlling expression type 'char [14]' not compatible with any generic association type
Run Code Online (Sandbox Code Playgroud)

更换char *char[]给我

error: type 'char []' in generic association incomplete
Run Code Online (Sandbox Code Playgroud)

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

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

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

我在Debian上使用clang 3.2.不幸的是,它是我访问过的唯一支持此功能的编译器,所以我不知道它是否是编译器错误.

Pas*_*uoq 20

这是一个解决方案:

#include <stdio.h>
#define foo(x) _Generic((0,x), char*: puts(x))

int main()
{
    foo("Hello, world!");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这编译并产生:

$ clang t.c && ./a.out 
Hello, world!
Run Code Online (Sandbox Code Playgroud)

这是有点跛,但我没有找到什么更好的方法,使x衰减到字符指针,也不符合其在模糊时尚型,你需要,与苹果LLVM 4.2版(铛- 425.0.28)(基于LLVM 3.2svn).

根据由延猛吹这篇博客文章,海湾合作委员会的行为是不同的(在GCC,字符串自动衰减中的指针_Generic方面,显然).

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

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

  • @MichaelRawson 6.5.1.1继续:"如果泛型选择具有与控制表达式类型**兼容**的类型名称的泛型关联,则泛型选择的结果表达式是该泛型关联中的表达式."和`const char*`与`char*`不兼容.我不希望任何常模糊.我的铿锵不允许任何我. (3认同)

250*_*501 14

我想出了一种避免使用聪明(0,x)伎俩的方法.

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

你如何获得这个尺寸?,使用sizeof运营商:

#include <stdio.h>

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

#include <stdio.h>
#define foo(x) _Generic( ( &*(x) ), char*: puts , const char*: puts )( x )

int main()
{
    foo("Hello, world!");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • `&*`是另一个"无所事事"的上下文,就像`0,`强制指针衰减一样,但是如果`x`不是一个指针(如果你想对两个浮点数都使用`_Generic`那么它将不起作用)字符串文字).你对`sizeof`的使用给我留下了深刻的印象. (5认同)

Ant*_*ala 5

Clang 的行为在3.7.1之前是不正确的(C11 缺陷报告 481)。它在2016 年 3 月 8 日发布的 Clang 3.8.0 中得到修复。

委员会对 DR 481 的回应如下:

这篇论文引发了一场长期而富有成效的讨论。委员会同意_Generic提案作者的观点,即明确避免选择符合条件的类型,就像按大小选择数组一样。的目的_Generic是为 C 提供一种机制,在某种程度上表达 C++ 中“重载函数”的概念,尤其是实现者用来实现第 7.17.7 节中的原子类型泛型函数的可能机制。