【发布时间】:2012-09-10 12:13:07
【问题描述】:
当尝试为多个平台编译以下(简化的)代码时,我发现它在某些平台上失败了,即 IBM 的 xlC_r。进一步的调查发现,它在 comeau 和 clang 上也失败了。使用 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", 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 错误:
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 错误:
"ComeauTest.c", line 8: error: "end", declared in for-loop initialization, may not
be redeclared in this scope
bool *jt = a2, *end = a2+1;
^
问题是为什么这是一个错误?
查看 2003 年标准,它说以下 (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
这里没有在条件中声明名称。
此外,它说 (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;
}
}
同样,我不确定这是否相关,因为条件中没有声明。因此,鉴于 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;
}
}
}
这显然会允许重新声明 end。
【问题讨论】:
-
好问题。 Comeau 的错误包括“ComeauTest.c”这一事实似乎很可疑。您能否检查
__cplusplus以确保它是在 C++ 模式下编译的? -
实际上,仔细观察,
bool的使用应该会在 C 模式下引发编译器错误,因为您没有包含<stdbool.h>。所以看起来它被编译为 C++,尽管有文件名。 -
很少(实际上不止几个)年前,编译器使
for变量在for之外可见是很常见的。 MSVC 6 或 5 做到了这一点。 -
你为什么要这样写?使代码更难阅读
-
为什么?因为它是重构的结果。显然我现在已经改变了它,但我很好奇为什么 IBM 拒绝看起来像有效的代码,更奇怪的是 comeau 和 clang 也拒绝它。
标签: c++ for-loop declaration