C99 之前的 C 在 for 循环中没有初始声明的原因是什么?
Rationale for pre-C99 C not having initial declarations in for loops?
为什么原来的C语言不支持for循环初始化中的初始声明?
显然,最初的创作者,以及 C99 之前的标准化,并没有那样指定。但我似乎无法找到 为什么 做出设计选择的任何理由。
我似乎找到的最接近答案的是 this answer 解释了如何禁止混合声明和代码以允许编译器在重要时单回传。乍一看,for 循环语句中的声明会出现 same/similar 问题,因为声明与代码混合在一起。
但是,C99 之前的 C 确实 支持块开头的声明:
{
unsigned int i;
for(i = 0; i < WHATEVER; i += 1)
{
/* ... */
}
}
我个人看不出它的编译器逻辑与此有何显着不同:
for(unsigned int i = 0; i < WHATEVER; i += 1)
{
/* ... */
}
在我看来,如果编译器可以执行前者的单次传递,那么它也可以执行后者。它可能需要 for
语句 always 创建一个范围块(即使后面只有一个语句而不是 { ... }
语句块),但我可以不要想出一种方法让这种语义破坏任何其他 C99 之前的 C 代码(要么 for 语句后跟一个块,在这种情况下它已经是 "scoped",要么它后跟一个语句,在这种情况下无论如何都不允许在该单个语句中进行新的声明)。
那么,为什么这个语法 "feature" 最初被省略了?我是否认为在不违反当时的绩效目标的情况下提供支持是微不足道的?当时已知的语言 parser/compiler 技术是否使它看起来更难?它是否因为极简主义 design/mentality 而被省略,因为在功能上可以做同样的事情(循环块周围)?或者是否有明确的语言设计原因反对它(例如,Go 最初是如何排除异常的,因为设计者认为这有助于更好的语言)?
我看过的地方
- 我已经尝试在这里和通过一般的网络搜索找到这个问题的答案,但没有运气:我想到的所有搜索词似乎都充满了关于 C for 循环初始声明的混淆问题,"used outside of C99 mode" 错误消息等(除了搜索词 "rationale",它引导我找到有用的信息,但没有具体回答这个问题)。
- 我搜索了 this article 丹尼斯里奇本人关于开发该语言的内容,但没有发现任何东西。
- 我搜索了我的 C 程序设计语言(第 2 版)副本,首先阅读了实际的 for 循环解释部分,然后检查了索引以查找 "for"/"for loop" 的其他提及。我已经阅读了其他几个我认为可能会提到它的地方,但一无所获。
我认为没有任何具体决定排除此类功能,也没有理由这样做。
尽管看起来设计师(Kernighan、Ritchie 等)考虑了所有的可能性,并且只有在深入而有意义的考虑之后才排除功能,但现实是设计 C 的早年(比如相当多的其他编程语言)遵循一种更为谦逊的哲学,比如“从小处着手,除非程序员被阻止做某事,否则不要为添加功能而烦恼”。
for
循环中的变量初始化等功能为程序员提供了方便 - 它们的缺席并没有阻止完成工作。因此,即使有人乞求或宣传这样的功能(可能没有),它的优先级顺序也可能下降。
至于事情是如何演变的.....
在 1999 年之前,变量声明位于 C 语言块的开头(代码以 {
开始并在结束 }
结束),而不是在其他语句中。这是事情最初在准标准 (K&R) C 和之前的语言如 B(实际上是之前的语言的缩减衍生物)中工作的方式。
for
循环中的变量 declaration/initialisation 首先引入 C++。它很早就出现了(例如 ARM 中的第 19 节),并最终在 1998 年底批准的第一个 C++ 标准中引入。
在起草 C++ 标准(花了十年)的过程中,C 标准委员会讨论了关于将 C++ 的某些特性引入 C 的过程。该讨论通常主要围绕“是否会否则在 C break 如果我们添加这个?”。许多编译器供应商已经在他们的 C 编译器中实现了几个这样的功能作为可选扩展(或者他们的 C 编译器实际上是 C++ 编译器,具有禁用与 C 不兼容的 C++ 功能的设置),因此关于添加这些功能的讨论非常简短。因此,那些很容易从 C++ 添加到 C 的特性出现在 1999 年的 C 标准中。 for
循环中的变量 declaration/initialisation 就是这些功能之一。
从那段历史来看,没有证据表明有任何特定的决定或理由将这些功能从早期 C 中排除 - 简而言之,可能只是没有想到。
为什么原来的C语言不支持for循环初始化中的初始声明?
显然,最初的创作者,以及 C99 之前的标准化,并没有那样指定。但我似乎无法找到 为什么 做出设计选择的任何理由。
我似乎找到的最接近答案的是 this answer 解释了如何禁止混合声明和代码以允许编译器在重要时单回传。乍一看,for 循环语句中的声明会出现 same/similar 问题,因为声明与代码混合在一起。
但是,C99 之前的 C 确实 支持块开头的声明:
{
unsigned int i;
for(i = 0; i < WHATEVER; i += 1)
{
/* ... */
}
}
我个人看不出它的编译器逻辑与此有何显着不同:
for(unsigned int i = 0; i < WHATEVER; i += 1)
{
/* ... */
}
在我看来,如果编译器可以执行前者的单次传递,那么它也可以执行后者。它可能需要 for
语句 always 创建一个范围块(即使后面只有一个语句而不是 { ... }
语句块),但我可以不要想出一种方法让这种语义破坏任何其他 C99 之前的 C 代码(要么 for 语句后跟一个块,在这种情况下它已经是 "scoped",要么它后跟一个语句,在这种情况下无论如何都不允许在该单个语句中进行新的声明)。
那么,为什么这个语法 "feature" 最初被省略了?我是否认为在不违反当时的绩效目标的情况下提供支持是微不足道的?当时已知的语言 parser/compiler 技术是否使它看起来更难?它是否因为极简主义 design/mentality 而被省略,因为在功能上可以做同样的事情(循环块周围)?或者是否有明确的语言设计原因反对它(例如,Go 最初是如何排除异常的,因为设计者认为这有助于更好的语言)?
我看过的地方
- 我已经尝试在这里和通过一般的网络搜索找到这个问题的答案,但没有运气:我想到的所有搜索词似乎都充满了关于 C for 循环初始声明的混淆问题,"used outside of C99 mode" 错误消息等(除了搜索词 "rationale",它引导我找到有用的信息,但没有具体回答这个问题)。
- 我搜索了 this article 丹尼斯里奇本人关于开发该语言的内容,但没有发现任何东西。
- 我搜索了我的 C 程序设计语言(第 2 版)副本,首先阅读了实际的 for 循环解释部分,然后检查了索引以查找 "for"/"for loop" 的其他提及。我已经阅读了其他几个我认为可能会提到它的地方,但一无所获。
我认为没有任何具体决定排除此类功能,也没有理由这样做。
尽管看起来设计师(Kernighan、Ritchie 等)考虑了所有的可能性,并且只有在深入而有意义的考虑之后才排除功能,但现实是设计 C 的早年(比如相当多的其他编程语言)遵循一种更为谦逊的哲学,比如“从小处着手,除非程序员被阻止做某事,否则不要为添加功能而烦恼”。
for
循环中的变量初始化等功能为程序员提供了方便 - 它们的缺席并没有阻止完成工作。因此,即使有人乞求或宣传这样的功能(可能没有),它的优先级顺序也可能下降。
至于事情是如何演变的.....
在 1999 年之前,变量声明位于 C 语言块的开头(代码以 {
开始并在结束 }
结束),而不是在其他语句中。这是事情最初在准标准 (K&R) C 和之前的语言如 B(实际上是之前的语言的缩减衍生物)中工作的方式。
for
循环中的变量 declaration/initialisation 首先引入 C++。它很早就出现了(例如 ARM 中的第 19 节),并最终在 1998 年底批准的第一个 C++ 标准中引入。
在起草 C++ 标准(花了十年)的过程中,C 标准委员会讨论了关于将 C++ 的某些特性引入 C 的过程。该讨论通常主要围绕“是否会否则在 C break 如果我们添加这个?”。许多编译器供应商已经在他们的 C 编译器中实现了几个这样的功能作为可选扩展(或者他们的 C 编译器实际上是 C++ 编译器,具有禁用与 C 不兼容的 C++ 功能的设置),因此关于添加这些功能的讨论非常简短。因此,那些很容易从 C++ 添加到 C 的特性出现在 1999 年的 C 标准中。 for
循环中的变量 declaration/initialisation 就是这些功能之一。
从那段历史来看,没有证据表明有任何特定的决定或理由将这些功能从早期 C 中排除 - 简而言之,可能只是没有想到。