当人们说C ++有“不可判断的语法”时,人们的意思是什么?

时间:2009-04-27 15:21:24

标签: c++ compiler-construction

人们说这话时意味着什么?对程序员和编译器有什么影响?

5 个答案:

答案 0 :(得分:55)

这与C ++的模板系统Turing complete有关。这意味着(理论上)您可以使用可以使用任何其他图灵完整语言或系统的模板在编译时计算任何内容。

这有副作用,一些显然有效的C ++程序无法编译;编译器永远无法决定程序是否有效。如果编译器可以决定所有程序的有效性,那么就可以解决Halting problem

注意这与C ++语法的歧义无关。


编辑: Josh Haberman在下面的评论和blog post中指出了一个很好的例子,为C ++构建一个解析树实际上是不可判定的。由于语法的模糊性,将语法分析与语义分析分开是不可能的,因为语义分析是不可判定的,语法分析也是如此。

另见(Josh的帖子链接):

答案 1 :(得分:13)

它可能意味着C ++语法在语法上是模糊的,你可以根据上下文写下一些可能意味着不同事物的代码。 (语法是对语言语法的描述。它决定a + b是一个加法运算,涉及变量a和b。)

例如,foo bar(int(x));,如所写的,可以是名为bar的变量的声明,类型为foo,其中int(x)是初始值设定项。它也可以是一个名为bar的函数声明,取一个int,并返回一个foo。这是在语言中定义的,但不是语法的一部分。

编程语言的语法很重要。首先,它是一种理解语言的方法,其次,它是编译的一部分,可以快速完成。因此,与C ++具有明确的语法相比,C ++编译器更难编写并且使用起来更慢。此外,更容易制作某些类型的错误,尽管一个好的编译器将提供足够的线索。

答案 2 :(得分:8)

如果“某些人”包括Yossi Kreinin,那么根据他写的内容here ...

  

考虑这个例子:

x * y(z);
     

在两种不同的背景下:

int main() {
    int x, y(int), z;
    x * y(z);
}
     

int main() {
    struct x { x(int) {} } *z;
    x * y(z);
}

......他的意思是“你不能通过查看x * y(z)决定它是表达式还是声明。”在第一种情况下,它表示“使用参数z调用函数y,然后使用x调用operator *(int,int)和函数调用的返回值,最后丢弃结果。”在第二种情况下,它意味着“y是指向结构x的指针,初始化为指向与z相同的(垃圾和时间炸弹)地址。”

假设您有COBOLmania并将DECLARE添加到该语言中。然后第二个将成为

int main() {
    DECLARE struct x { x(int) {} } *z;
    DECLARE x * y(z);
}

将出现可判定性。请注意,可判定结果不会使指针垃圾问题消失。

答案 3 :(得分:4)

'不可判断的语法'是一个非常糟糕的单词选择。一个真正不可判定的语法就是没有语法解析器会终止所有可能的输入。它们可能意味着C ++语法不是无上下文的,但即使这也是一种品味问题:在语法和语义之间划清界限?任何编译器都只允许通过解析器阶段的那些程序的正确子集而没有语法错误,并且只有这些程序的正确子集实际上没有错误地运行,因此没有语言真正无上下文甚至可判定(除非某些深奥的语言)

答案 4 :(得分:2)

我们这些使用该语言的含义是错误消息可能变得非常奇怪,非常快(实际上这并不是什么大问题.STL库错误通常比你最终得到的错误更糟糕语言语法。)

编写编译器的人的含义是他们必须花费大量额外的时间和精力来编写语言。