6

为什么原始 C 语言不支持 for 循环初始化中的初始声明?

显然,最初的创造者,然后是 C99 之前的标准化,并没有这样指定。但我似乎找不到任何理由来解释为什么做出这种设计选择。

我似乎找到的最接近答案的是这个答案,它解释了如何禁止混合声明和代码,以便在重要时允许编译器单次返回。乍一看,for 循环语句中的声明与混合代码的声明具有相同/相似的问题是有道理的。

但是,C99 之前的 C确实支持块开头的声明:

{
    unsigned int i;
    for(i = 0; i < WHATEVER; i += 1)
    {
        /* ... */
    }
}

我个人没有看到编译器逻辑与此有何本质不同:

for(unsigned int i = 0; i < WHATEVER; i += 1)
{
    /* ... */
}

在我看来,如果编译器可以执行前者的单遍,它也可以执行后者。它可能要求一个for语句总是创建一个范围块(即使后面只有一个语句而不是一个语句{ ... }块),但我想不出这种语义破坏任何其他 C99 之前的 C 代码的方法(或者for 语句后跟一个块,在这种情况下它已经“作用域”,或者它后面跟着一个语句,在这种情况下,无论如何都不允许在该单个语句中使用新声明)。

那么,为什么最初省略了这个语法“功能”?我认为在不违反当时的性能目标的情况下支持是微不足道的,我错了吗?当时已知的语言解析器/编译器技术是否使它看起来更难?它只是因为极简设计/心态而被省略了吗,因为在功能上可以做同样的事情(阻塞 for 循环)?或者是否有明确的语言设计理由反对它(例如,Go 最初是如何排除异常的,因为设计者认为这会产生更好的语言)?

我看过的地方

  • 我已经尝试在这里和通过一般的 web-search-fu 找到答案,但没有运气:我想到的所有搜索词似乎都充斥着关于 C for loop 初始声明的困惑问题,“在 C99 模式之外使用” ” 错误消息等(除了搜索词“基本原理”,它引导我找到有用的信息,但没有具体回答这个问题)。
  • 我搜索了Dennis Ritchie 本人关于开发该语言的这篇文章,但没有发现任何内容。
  • 我搜索了我的 C 编程语言(第 2 版)的副本,首先阅读了实际的 for 循环解释部分,然后检查了索引中其他提到的“for”/“for 循环”。我已经阅读了其他几个我认为可能会提到它的地方,但一无所获。
4

1 回答 1

11

我不相信有任何具体决定要排除这些功能,也没有理由这样做。

设计师(Kernighan、Ritchie 等)似乎认为设计者(Kernighan、Ritchie 等)考虑了所有可能性,并在经过深入而有意义的考虑后才排除功能,但现实是,设计 C 的早期(就像许多其他编程一样)语言)遵循更谦逊的理念,例如“从小处着手,不要为添加功能而烦恼,除非程序员被阻止做某事”。

循环中的变量初始化等特性for为程序员提供了便利——它们的缺失并没有阻止事情的完成。因此,即使有人乞求或争取这样的功能(可能没有),它也可能按优先级顺序下降。

至于事情是如何演变的......

在 1999 年之前,变量声明位于 C 中块的开头(代码以 开头{和结尾}),而不是在其他语句中。这是最初在准标准 (K&R) C 和之前的语言(如 B)中工作的方式(实际上是之前语言的缩减派生词)。

循环内的变量声明/初始化for首先被引入到 C++ 中。它很早就出现了(例如 ARM 中的第 19 节),并最终在 1998 年底批准的第一个 C++ 标准中引入。

C 标准委员会在起草 C++ 标准的过程中(花了十年时间)就将 C++ 的某些特性引入 C 进行了一些讨论。讨论通常主要是“如果 C我们添加了这个?”。许多编译器供应商已经在他们的 C 编译器中实现了几个这样的特性作为可选扩展(或者他们的 C 编译器实际上是 C++ 编译器,设置禁用与 C 不兼容的 C++ 特性),所以关于添加这些特性的讨论非常简短。因此,那些从 C++ 轻松添加到 C 中的特性出现在 1999 年的 C 标准中。循环内的变量声明/初始化for是这些功能之一。

从那段历史来看,没有证据表明有任何特定的决定或理由将这些特征从早期 C 中排除——简而言之,它可能根本没有被考虑过。

于 2016-01-31T07:24:56.467 回答