【问题标题】:Why can int _$[:>=<%-!.0,}; compile?为什么 int _$[:>=<%-!.0,};编译?
【发布时间】:2015-11-07 05:04:30
【问题描述】:

今天我发现了奇怪的语法,比如

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

在一些旧代码中,但实际上代码没有注释。这行似乎没有编译错误的报告。我单独测试过,也可以编译:

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

为什么可以编译?

【问题讨论】:

  • @dcow C 编译器接受 C 作为 source 语言。我没有混淆任何东西。显然你认为 gcc 是一个 C 编译器。它不是。它接受一种称为 GNU C 的语言,其中 $ 在标识符中是可以接受的。在标准 C 中,这是一个必须诊断的语法错误。要将 gcc 转换为 C 编译器,您需要提供一组深奥的选项,例如 -ansi -pedantic -Wno-trigraph 左右,即使这样它也可能接受一些非 C 程序。 C 由 ISO9899 定义,而不是由某些随机编译器接受的语言定义。
  • 这行代码除了混淆读者和编译器还有其他目的吗?除非这是来自一些混淆的 C 竞赛,否则谁能将这些随机符号混在一起?
  • 在 stackoverflow 上每天都会被问到有向图。我不明白为什么同一个问题有这么多副本会出现在热门问题列表中……或者为什么它们没有作为重复项关闭。
  • 如何在 SO 上获得大量支持: 1. 用有向图编写一些时髦的 C 代码。 2. 发布关于它的问题 3. 利润!!!

标签: c syntax


【解决方案1】:

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

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

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

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


C11 §6.4.6 标点符号

在语言的所有方面,六个标记

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

分别表现得与六个令牌相同

[  ]  {  }  #  ##

【讨论】:

  • 你为 gcc 提供了哪些选项?使用带有-std=c11 -pedantic -Wall -Wextra 的gcc-4.8 甚至不会发出警告。如果我将 -std=c11 替换为 -std=c89,那么它会在 $ 上发出警告并拒绝有向图。
  • @rici 你说得对,gcc 编译得很好,我会编辑帖子。当我尝试它时,我错误地认为没有int(就像许多混淆代码一样),所以我使用-std=c89 来确保启用了隐式int,并且gcc 在未声明的_$ 上给出了错误。
  • 包含$ 的标识符在VMS 中显然很常见。
  • 你能不能把~(按位否定)和其他一元运算符一起扔进去?
【解决方案2】:

嗯,

  • 下划线_ 是允许的标识符字符,
  • 美元符号$ is allowed in some implementations too,
  • 左括号[表示类型应该是数组,
  • :&gt;] 的有向图,
  • 等于= 是赋值,
  • &lt;%{ 的有向图,
  • -!.0 只是 -1(.0 是一个双重文字 0.0! 隐式转换为 (int) 0 并在逻辑上反转它,- 是负数),
  • 您可以在数组初始值设定项 {1, (2, 3,)}, 中使用尾随逗号,
  • ; 结束语句。,

所以你得到

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

【讨论】:

    【解决方案3】:

    如果我们替换代码行中的二合字母 :&gt;&lt;%,我们最终会得到

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

    相当于

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

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

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

    【讨论】:

      【解决方案4】:

      这得益于 C 语言中的 digraphs。有问题的行解码如下:

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

      此外:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-22
        • 2010-09-06
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-08
        相关资源
        最近更新 更多