为什么int _ $ [:> = <% - !.0,}; 编译?

ggr*_*grr 43 c syntax

今天我发现了奇怪的语法

 int _$[:>=<%-!.0,};
Run Code Online (Sandbox Code Playgroud)

在一些旧代码中,但实际上代码没有被注释.似乎没有关于此行的编译错误的报告.我单独测试它也可以编译:

int main(){
    int _$[:>=<%-!.0,};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么要编译?

Yu *_*Hao 47

使用Digraph(见下文),该行转换为:

int _$[]={-!.0,};
Run Code Online (Sandbox Code Playgroud)

在右侧,.0double文字,!是逻辑否定运算符,-是算术否定运算符,并且,是尾随逗号.Together {-!.0,}是一个数组初始化器.

左侧int _$[]定义了一个int数组.但是,最后一个问题,_$不是标准C中的有效标识符.某些编译器(例如,gcc)支持它作为扩展.


C11§6.4.6标点符号

在语言的各个方面,六个令牌

<: :> <% %> %: %:%:
Run Code Online (Sandbox Code Playgroud)

行为分别与六个令牌相同

[  ]  {  }  #  ##
Run Code Online (Sandbox Code Playgroud)


dco*_*cow 38

好,

  • 下划线_是允许的标识符字符,
  • $在某些实现中也允许使用美元符号,
  • 左括号[表示类型应为数组,
  • :>是有图的],
  • 等于=分配,
  • <%是有图的{,
  • -!.0只是-1(.0是一个双字面0.0,!隐式转换(int) 0并逻辑反转它,并且-是负数),
  • 你可以在数组初始化器{1,(2,3,)}中有尾随逗号,
  • ;结束声明.,

所以你得到了

int _$[] = {-1,};
Run Code Online (Sandbox Code Playgroud)


Nay*_*uki 11

这可以归功于C中的有向图.问题的行解码如下:

int _$ [ :> = <% - ! .0  , } ;
int _$ [ ]  = {  - ! 0.0 , } ;
Run Code Online (Sandbox Code Playgroud)

此外:

  • .0是一个double文字.
  • !是布尔否定运算符,所以!.0得到(int) 1.
  • -是一元否定运算符,它产生(int) -1.
  • 尾随逗号在数组元素之后是合法的.


AnT*_*AnT 11

如果我们替换了有向图:><%出现在您的代码行中,我们最终会得到

int _$[]={-!.0,};
Run Code Online (Sandbox Code Playgroud)

这相当于

int _$[] = { -1, };
Run Code Online (Sandbox Code Playgroud)

它是带有初始化器_$的类型数组的声明int [1].

请注意,这并不能完全保证编译,因为标准C语言不会立即为$标识符中的字符提供支持.它允许实现扩展支持的字符集.显然,您使用的编译器支持$标识符.