为什么我不能在 for 循环的初始语句中声明多个变量?

Why can't I declare more than one variable in a for loop's initial statement?

当 a 与一个变量一起使用时,我们将其声明为 0,因为 i=0 就像这里一样

但是当我们使用两个变量时,就好像我添加了 n = strlen 以使代码更高效,然后没有声明 i=0 而是使用逗号并声明了 n=strlen(s) 。为什么我们不能像前面的代码那样在这里使用 'i=0;' 呢?

编辑:cs50.h 是哈佛制作的沙箱 cs50 的一部分。

#include <stdio.h>
#include <string.h>

int main(void)
{
    string s = get_string("Input:  ");
    printf("Output: ");
    for (int i = 0; i < strlen(s); i++)
    {
        printf("%c\n", s[i]);
    }
}
#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    string s = get_string("Input: ");
    printf("Output:\n");
    for (int i = 0, n = strlen(s); i < n; i++)
    {
        printf("%c\n", s[i]);
    }
}

不确定我是否理解这个问题(虽然我喜欢它)。您的两个代码片段都有效,不是吗?请注意,我们不知道 cs50.h 中的内容,但我尝试编译它,并且它有效(编译和 运行)。

#include <stdio.h>
#include <string.h>

int main(void) {
  char *s = "Hello world!";
  printf("Output:\n");
  for (int i = 0, n = strlen(s); i < n; i++) {
    printf("%c\n", s[i]);
  }
}

这里有两件事可能相关; - for 的工作原理和 - 变量 declaration/initialization 是如何工作的。

你可以这样想forfor(AAA; BBB; CCC) DDD;

相同
{ // Important!
  AAA;
  while(BBB) {
    {
      DDD;
    }
    CCC;
  }
} // Important!

// Important! 大括号很重要,因为 for 引入了一个新的作用域,即 in 将无法访问 outside/after for 循环.

另一件事是declaration/initialization。所以

int i = 0, n = strlen(s);

是两个变量的初始化:in。我不是 100% 确定正确的词汇和规则(你可以参考标准),但我的想法是声明看起来像: TYPE VAR1, VAR2, ..., VARn 其中 VARx 是声明的变量名,或者 "assignment" 在这种情况下它是一个初始化。

UPDATE/PART2: 通常我会怎么做是这样的:

const int len = strlen(s);
// Good practice to declare const what every you know wont change
for(int i = 0; i < len; i++) {
  // whatever
}

但是,如果可以使令人困惑的 coma/semicolon 保持一致,并且由于分号是 必须的 让我们尝试使所有内容都成为分号,我试过这个:

for ({int i = 0; int n = strlen(s); }; i < n; i++) {
  // what ever
}

这没有编译,但它也没有意义,因为如果这会有 "worked"(在某种意义上我认为我可以但实际上不能),in 将在小块中声明,并且在其他任何地方都无法访问,即在 i < n 中将无法访问。因此,为了使它们易于访问,我们可以尝试这样做:

int i, n;
for ({i = 0; n = strlen(s); }; i < n; i++) {
  printf("%c\n", s[i]);
}

现在,如果上述 for-while 等价性 100% 正确,那么这应该有效,但显然 AAA 必须是单个语句(通常是一个声明)并且它不能是一个块,即 {...}。确切的编译器错误:

cc     hola.c   -o hola
hola.c: In function ‘main’:
hola.c:8:8: error: expected expression before ‘{’ token
    8 |   for ({
      |        ^
make: *** [<builtin>: hola] Error 1

但是正如你所看到的,它已经非常丑陋了......所以是的,你需要使用 , 来分隔 declarations/initializations 和 ; 来终止它.

来自C标准ISO/IEC 9899:TC3 / ISO/IEC 9899/C11,语法for 语句的描述,§(6.8.5) 迭代语句,有 2 种不同的形式:

for ( expression_opt ; expression_opt ; expression_opt ) statement

for (declaration expression_opt ; expression_opt ) statement

请注意,在第一种形式中,我们在第一个位置有一个表达式,尽管它作为所有 3 个字段都是可选的,并且语句形式的所有 3 个部分都由 ; 分号分隔,用作一个分隔符。

在第二种形式中,我们可以看到括号中的第一个元素是声明而不是表达式,我们还可以注意到没有分号分隔它。这是因为 声明本身总是以分号结束 .

段落(6.7)声明描述了声明的语法:

declaration-specifiers init-declarator-list_opt ;

如您所见,declaration 总是以分号结尾。

声明当然可以采用多个声明的形式,如您的初始化:

for (int i = 0, n = strlen(s); i < n; i++)
{
    printf("%c\n", s[i]);
}

所以 您使用的是第二种形式,其中分号分隔声明(不是 for 的第一部分)

使用多个分号只是语法错误。