【问题标题】:Why is "true;" (and others) a valid line of code C++?为什么是“真”; (和其他人)有效的代码行 C++?
【发布时间】:2015-07-29 04:51:26
【问题描述】:

添加 true; / false; 显然是有效的 C++ 代码。它编译并运行得很好。

类似地,int;void;{}(no ())、1+1;1 == 1; 甚至只是 1; 之类的语句也是如此……为什么? (我使用的是 Visual C++)

【问题讨论】:

  • 因为他们没有理由不运行。但是,仅使用关键字或您提到的其他一些示例将无济于事。
  • 我问的原因是因为这样的东西在 java 中不起作用,而且可能在大多数语言中都不起作用。
  • int;void; 无效。
  • 任何后跟分号的表达式都是有效的语句。没有副作用的表达式作为语句有点毫无意义,但仍然有效。这占true;false;1+1;1==1;1;{} 是一个恰好为空的复合语句 - 作为函数体或循环体很常见。 'int;'似乎无效,不应编译(gcc 拒绝它)。
  • @MattMcNabb 嗯,为什么我的编译器允许它:(

标签: c++ c++11 visual-c++ compilation


【解决方案1】:

为什么不呢?语言规范明确指出,C++ 中的表达式语句如下所示

<expression>;

这正是您在 true;1 == 1;1; 等示例中的内容。

{} 只是一个空的复合语句。

同时,int; 格式不正确。如果编译器安静地接受它,它一定是某种编译器特定的怪癖/错误/扩展。

【讨论】:

  • 我问的原因是因为这样的东西在 java 中不起作用,而且可能在大多数语言中都不起作用。
【解决方案2】:

false;true; 是有效的语句。它们分别评估为falsetrue,没有副作用。

但是,int; 不是有效的声明。如果 VS 允许,那就是 VS 的一个 bug。

{}; 是一个空的复合或块语句{} 和一个空的statemet ;。两者都是合法的构造。

1 == 1; 是法律声明。它的计算结果为true,没有副作用。

1; 是法律声明。它的计算结果为1,没有副作用。

【讨论】:

    【解决方案3】:

    这些是有效的代码行,因为没有理由不让它们不存在 - 事实上,要让它们不存在需要额外的努力,而语言设计者不想经历这些额外的努力。 (但是,在 C# 等某些语言中,其中许多是无效的)。

    C++ 将“语句”(以分号结尾的内容)定义为一些特定的语句,例如return xthrow y,或任何表达式。必须允许使用表达式,以便 foo(); 等语句有效。语言设计者可以明确定义一个语句来包含函数调用和其他一些东西,而不是只包含任何表达式,但是只说任何表达式更容易。这包括true;false;1+1;1==1;1;等。

    在花括号的情况下,实际上允许(有时也有用)制作没有关联if/while/for/等的花括号。他们声明了一个新的范围。例如,以下打印出2

    void foo() {
        int x = 2;
        {
            int x = 3;
        }
        cout<<x<<endl; //prints 2
    }
    

    语言规范可以(大约)表示为一种称为上下文无关语法的东西,您可以在 Wikipedia 上找到有关此的更多信息。

    【讨论】:

    • C++ 的语法绝对不是上下文无关的。
    • C++ 语法是上下文无关的,但程序是否有效是图灵完备的。具体来说,您可以实现一个编译器,该编译器可以使用 CFG 解析 C++ 代码,但在 语义分析 (包括类型检查等)时失败。例如,`void x() { x++; } 根据语法是有效的,但在语义上仍然是无效的,因为你不能增加一个函数。
    • 我已经读过了 :) 这是一个很好的例子,说明程序的有效性是图灵完备的。不过,请看第二个答案 - jpalecek 很好地解释了语法的上下文无关语法性质。
    • @IanPudney C++ 语法绝对不是上下文无关的。经典示例:A * B; 在语法上可以是声明或表达式语句,具体取决于名称查找确定 A 是指类型还是变量。如果不考虑结构出现的上下文,就无法确定应用哪种语法产生式。
    【解决方案4】:

    void;int; 的格式不正确,如前所述(让我们把它们排除在外)。

    静态分析器和代码检查工具会通知您其余的表达式毫无意义或可能错误。一些 C++ 编译器甚至会发出警告。

    C++ 接受这些东西的原因是因为C 语法也接受了它们,并且继承了这一传统。关于'为什么 C 接受它们?' 的答案很简单,即该语言有很多部分是“编译器驱动的”,即为简化编译器编写者的工作而设计的。

    在名为“2000 万美元的错误”的书 'Deep C secrets' 中有一个很好的例子,结果证明是一行:

    x == 2; 
    

    一个完全没有意义的陈述,应该是一个赋值;没有警告没有错误(在他们发现错误之前没有钱)

    【讨论】:

      【解决方案5】:

      如果您的函数返回值 0 或 1(基本上是任何数字)(true / false)或表达式可以被评估,那么它将导致 true 或 false:

      例如,如果你写:

      int func() {
          return true;
      }
      while ( func() ) {
          ...
      }
      

      它将使用 true。

      【讨论】:

        猜你喜欢
        • 2022-10-07
        • 2012-11-04
        • 2017-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-09
        相关资源
        最近更新 更多