在C ++中for循环中的变量的重写 [英] Redeclaration of a variable in a for-loop in C++

查看:161
本文介绍了在C ++中for循环中的变量的重写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当尝试为多个平台编译以下(简化)代码时,我发现它在某些方面失败,即IBM的xlC_r。进一步的调查发现,它也失败了来和ang。它用g ++和Solaris的CC编译成功。



这里是代码:

  int main()
{
int a1 [1];
bool a2 [1];

for(int * it = a1,* end = a1 + 1; it!= end; ++ it){
// ...
bool * jt = a2,* end = a2 + 1;
// ...
}
}

xlC_r错误:

 main.cpp,第8.25行:1540-0400(S)end 
main.cpp,行6.25:1540-0425(I)end在main.cpp的第6行定义。

clang错误:

  main.cpp:8:25:error:redefinition的'end'类型不同
bool * jt = a2,* end = a2 + 1;
^
main.cpp:6:25:注意:以前的定义在这里
for(int * it = a1,* end = a1 + 1; it!= end; ++ it ){
^

comeau错误:


$ b b

 ComeauTest.c,第8行:错误:end,在for循环初始化中声明,可能不
在此范围内重新声明
bool * jt = a2,* end = a2 + 1;
^

问题是为什么是错误?



通过2003年的标准,它说如下(6.5.3):

 语句
for(for-init-statement; condition; expression)语句
相当于
{
for-init-statement;
while(condition){
statement;
expression;
}
}
,但在for-init语句中声明的名称与在条件中声明的
声明性区域相同


此外,它说(6.5) .1):

 当while语句的条件是声明时,变量的范围
声明从声明
(3.3.1)延伸到while语句的结尾。 while语句
while(T t = x)语句
等价于
标签:
{
T t = x;
if(t){
语句;
goto label;
}
}

同样,我不确定这是否相关,因为在条件中没有声明。所以给定从6.5.3的等价重写,我的代码应该是相同的:

  int main()
{
int a1 [1];
bool a2 [1];

{
int * it = a1,* end = a1 + 1;
while(it!= end){
// ...
bool * jt = a2,* end = a2 + 1;
// ...
++ it;
}
}
}

解决方案

标准有点模棱两可。您引用的代码等同于循环意味着有一个内部作用域,其中循环中的声明可以隐藏条件中的声明;但是标准也说(引用C ++ 11,因为我没有C ++ 03方便):


6.4 / 2条件规则适用于选择语句和 for while 语句



6.4 / 3如果在条件控制的子句的最外面的块中重新声明了名称,那么重新声明名字的声明是不成立的。



在for-init语句中声明的6.5.3 / 1个名称与在条件

中声明的声明域相同。

它们之间的意思是不能重命名这些名称。



旧的for-init语句放入循环外的声明区域。这意味着你的代码是有效的,但这不会:

  for(int i = ...; .. 。...){...} 
for(int i = ...; ...; ...){...} //错误:redeclaration的i


When trying to compile the following (simplified) code for multiple platforms, I found that it was failing on some, namely IBM's xlC_r. Further investigation has found that it also fails on comeau and clang. It compiles successfully with g++ and Solaris's CC.

Here is the code:

int main()
{
    int a1[1];
    bool a2[1];

    for (int *it = a1, *end = a1+1; it != end; ++it) {
        //...
        bool *jt = a2, *end = a2+1;
        //...
    }
}

xlC_r error:

"main.cpp", line 8.25: 1540-0400 (S) "end" has a conflicting declaration.
"main.cpp", line 6.25: 1540-0425 (I) "end" is defined on line 6 of "main.cpp".

clang error:

main.cpp:8:25: error: redefinition of 'end' with a different type
        bool *jt = a2, *end = a2+1;
                        ^
main.cpp:6:25: note: previous definition is here
    for (int *it = a1, *end = a1+1; it != end; ++it) {
                        ^

comeau error:

"ComeauTest.c", line 8: error: "end", declared in for-loop initialization, may not
          be redeclared in this scope
          bool *jt = a2, *end = a2+1;
                          ^

The question is why is this an error?

Looking through the 2003 standard, it says the following (6.5.3):

The for statement
    for ( for-init-statement; condition; expression ) statement
is equivalent to
    {
        for-init-statement;
        while ( condition ) {
            statement;
            expression;
        }
    }
except that names declared in the for-init-statement are in the same
declarative-region as those declared in condition

Here there are no names declared in condition.

Further, it says (6.5.1):

When the condition of a while statement is a declaration, the scope
of the variable that is declared extends from its point of declaration
(3.3.1) to the end of the while statement. A while statement of the form
    while (T t = x) statement
is equivalent to
    label:
    {
        T t = x;
        if (t) {
            statement;
            goto label;
        }
    }

Again, I'm not sure this is relevant, as there is no declaration in the condition. So given the equivalent re-write from 6.5.3, my code should be the same as:

int main()
{
    int a1[1];
    bool a2[1];

    {
        int *it = a1, *end = a1+1;
        while (it != end) {
            //...
            bool *jt = a2, *end = a2+1;
            //...
            ++it;
        }
    }
}

Which obviously would allow end to be re-declared.

解决方案

The standard is somewhat ambiguous. The code you quote as being equivalent to a while loop implies that there is an inner scope where declarations inside the loop could hide declarations in the condition; however the standard also says (quoting C++11, since I don't have C++03 handy):

6.4/2 The rules for conditions apply both to selection-statements and to the for and while statements

6.4/3 If the name is re-declared in the outermost block of a substatement controlled by the condition, the declaration that re-declares the name is ill-formed.

6.5.3/1 names declared in the for-init-statement are in the same declarative-region as those declared in the condition

which between them imply that the names can't be redeclared.

Older (pre-1998) versions of the language put declarations in the for-init-statement into the declarative region outside the loop. This meant that your code would be valid, but this wouldn't:

for (int i = ...; ...; ...) {...}
for (int i = ...; ...; ...) {...}  // error: redeclaration of i

这篇关于在C ++中for循环中的变量的重写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆