为什么可以int _ $ [:> = <% – !。0,}; 编译?

今天我发现了一些奇怪的语法

int _$[:>=<%-!.0,}; 

在一些旧的代码中,但实际上代码没有被评论。 这条线似乎没有编译错误报告。 我单独testing它也可以编译:

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

为什么可以编译?

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

 int _$[]={-!.0,}; 

在右侧, .0double字面! 是逻辑否定运算符, -是算术否定运算符,并且是尾随逗号。 一起{-!.0,}是一个数组初始值设定项。

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


C11§6.4.6标点符号

在语言的所有方面,这六个令牌

 <: :> <% %> %: %:%: 

performance得分别与六个令牌相同

 [ ] { } # ## 

好,

  • 下划线_是一个允许的标识符字符,
  • 美元符号$在某些实现中也是允许的 ,
  • 左括号[表示types应该是数组,
  • :>是有向图]
  • 等于=是赋值,
  • <%{的有向图,
  • -!.0只是-1( .0是一个双字面量0.0 ,!隐式地转换为(int) 0并逻辑反转,而-为负值),
  • 数组初始值设定项{1,(2,3,)}中可以有尾随逗号,
  • ; 结束声明。

所以你明白了

 int _$[] = {-1,}; 

如果我们replace你的代码行中的有向图:><% ,我们就结束了

 int _$[]={-!.0,}; 

相当于

 int _$[] = { -1, }; 

它是一个具有初始值的types为int [1]的数组_$的声明。

请注意,由于标准C语言不能立即为标识符中的$字符提供支持,因此不能完全保证编译。 它允许实现扩展一组受支持的字符。 显然你使用的编译器在标识符中支持$

这是因为C中的有向图 。所讨论的行解码如下:

 int _$ [ :> = <% - ! .0 , } ; int _$ [ ] = { - ! 0.0 , } ; 

此外:

  • .0是一个double字面意思。
  • ! 是布尔否定运算符,所以!.0得出(int) 1
  • -是一元否定运算符,它产生(int) -1
  • 数组元素后面的逗号是合法的。