显然,您可以在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)) ...
这不是我想要的。
答案 0 :(得分:12)
'03标准中条件的语法定义如下:
condition:
expression
type-specifier-seq declarator = assignment-expression
因此上述内容仅允许以下条件:
if ( i && j && k ) {}
if ( (i = j) ==0 ) {}
if ( int i = j ) {}
标准允许条件声明一个变量,但是,他们通过添加一个名为'condition'的新语法规则来实现,该规则可以是一个表达式,也可以是一个带有初始值设定项的声明符。结果是,仅仅因为您处于if
,for
,while
或switch
的状态并不意味着您可以在表达式中声明变量。
答案 1 :(得分:11)
问题是,标准允许在括号内使用声明。你想要做的是将声明作为表达的一部分,这是标准不允许你做的事情。
while()可以有两种语法之一:while(< declaration>)或while(< expression>)。声明使用“=”,看起来像表达式,但它是一个不同的语法实体。
写作时
while(int i = 1) {
}
,这很好。 “int i = 1”是一个声明。但是,你想要的是
while ( (int i = 1) + 3) {
}
这是一种非常不同的动物。你想在while()中有一个表达式,其中表达式的一个术语是声明。现在,声明是一种陈述,因此不能成为表达的一部分。这就是为什么你需要做的事情无法完成的原因。
(在写完整个咆哮之后,我注意到另外两个人写了同样的东西。哦,好吧,越多越好。)
答案 2 :(得分:10)
这似乎不是合规行为。标准的第6.5.1.2部分规定:
当while语句的条件是声明时,声明的变量的范围会扩展 从声明(3.3.1)到while声明的结尾。一段时间的表格陈述
while(T t = x)陈述
相当于
label:
{ //start of condition scope
T t = x;
if (t) {
statement
goto label;
}
}
因此,在您的示例中,ch应该在循环的范围内声明并正常工作(通过每次循环迭代重新创建它)。观察到的行为的原因很可能是由于编译器没有正确确定变量的范围,然后多次声明它。
答案 3 :(得分:2)
这可能是因为每个循环都会计算while子句的内容,因此它会尝试多次声明“ch”。
你给出的if,switch和for循环示例都只有“ch”被定义一次。
答案 4 :(得分:2)
你可以在while循环的测试表达式中放置一个变量声明。你不能做的是在其他表达式中放置一个声明语句。例如,在表达式a + b + c中,您不能用int i = f()
替换b。表达式(a)
也是如此;您无法插入int i=f()
来获取表达式(int i=f())
。
因此,在while (int i = foo())
中,最外面的括号是while语句的一部分,而不是text-expression的一部分,并且一切都是合法的。在while ((int i = foo()))
中,最外面的括号仍然是while语句的一部分。 test-expression的格式为"(" expr ")"
,最终会出现语法错误。
答案 5 :(得分:0)
尝试 这不起作用
while (int ch = stream.get(), ch != -1) ...
我从来没有尝试过,但如果您的编辑中的评论是正确的,那么这应该可行。
VS 2005甚至不会编译它。