代码之家  ›  专栏  ›  技术社区  ›  Ferruccio

为什么我不能将变量声明放在while循环的测试部分?

c++
  •  17
  • Ferruccio  · 技术社区  · 16 年前

    显然,您可以将变量声明放在for循环中:

    for (int i = 0; ...
    

    我注意到在if和switch语句中也可以做同样的事情:

    if ((int i = f()) != 0) ...
    
    switch (int ch = stream.get()) ...
    

    但当我尝试在while循环中做同样的事情时:

    while ((int ch = stream.get()) != -1) ...
    

    编译器(VC++9.0)根本不喜欢它。

    编辑 :我发现我可以做到这一点:

    while (int ch = stream.get() != -1) ...
    

    但由于优先规则,这被解释为:

    while (int ch = (stream.get() != -1)) ...
    

    这不是我想要的。

    6 回复  |  直到 8 年前
        1
  •  14
  •   Richard Corden    16 年前

    condition:
      expression
      type-specifier-seq declarator = assignment-expression
    

    因此,上述仅允许以下条件:

    if ( i && j && k ) {}
    if ( (i = j) ==0 ) {}
    if ( int i = j ) {}
    

    该标准允许条件声明变量,但是,他们通过添加一个名为“条件”的新语法规则来声明变量,该规则可以是表达式或带有初始值设定项的声明器。结果是,仅仅因为你处于 if for , while switch 并不意味着您可以在表达式中声明变量。

        2
  •  13
  •   user3458 user3458    7 年前

    问题是,标准允许您 公告 括号内。您想要做的是将声明作为表达式的一部分,这是标准不允许您做的事情。

    while()可以有两种语法之一:while(<declaration>)或while(<expression>)。声明使用“=”,看起来像表达式,但它是一个不同的语法实体。

    当你写作时

    while(int i = 1) {
    }
    

    ,那太好了。“inti=1”是一个声明。然而,你想要的是

    while ( (int i = 1) + 3) {
    }
    

    这是一种完全不同的动物。您希望在while()中包含一个表达式,其中表达式的一个术语是声明。现在,声明是一个语句,因此不能作为表达式的一部分。这就是为什么你需要做的不能做。

        3
  •  11
  •   workmad3    16 年前

    这似乎不是顺从的行为。本标准第6.5.1.2部分规定:

    当while语句的条件是声明时,声明的变量的范围将扩展 从声明点(3.3.1)到while语句末尾。形式的while语句

    相当于

    label:
    { //start of condition scope
        T t = x;
        if (t) {
            statement
            goto label;
        }
    }
    

    因此,在您的示例中,ch应该在循环的范围内声明并正确工作(通过每次循环迭代重新创建)。观察到的行为的原因很可能是编译器没有正确地确定变量的作用域,然后多次声明它。

        4
  •  2
  •   RB.    16 年前

    这可能是因为while子句的内容在每个循环中都被求值,因此它会多次尝试并声明“ch”。

    您给出的if、switch和for循环示例都将只定义一次“ch”。

        5
  •  2
  •   MSalters    16 年前

    可以 do是将声明语句放在其他表达式中。例如,在表达式a+b+c中,不能将b替换为 int i = f() . 表达式也是如此 (a) ; 你不能插入 int i=f() (int i=f()) .

    那么在 while (int i = foo()) ,最外面的括号是while语句的一部分,而不是文本表达式的一部分,并且所有内容都是合法的。在里面 while ((int i = foo())) ,最外面的括号仍然是while语句的一部分。测试表达式的形式为 "(" expr ")"

        6
  •  0
  •   Mark Ransom    16 年前

    尝试 这不管用

    while (int ch = stream.get(), ch != -1) ...
    


    VS2005甚至不会编译它。