#include <iostream>
int main(){
int b = 2;
if(int a = 0){ // #condition
}else if(b == 2){
int a; //#1
}
}以上代码可以是gcc和clang的编译好的代码。然而,根据有关规定,这一守则应该是不正确的.这些规则是:
由条件中的声明引入的名称(由decl-说明符-seq或条件的声明者引入)从声明点一直到条件控制的子语句结束为止。如果名称在条件控制的子语句的最外层块中重新声明,则重声明名称的声明格式不正确。
else后面的if语句不是由条件控制的子语句吗?(也就是说,只有在#condition执行为false的条件下,else之后的if-语句才会被执行)。那么,为什么在这样一个子语句的最外层块中重新声明名称的声明可以被认为是格式良好的代码呢?
也许在版本n4659的规则中,对于“由条件控制的子语句”这一短语有一些争论,然而,这种想法在最新的草案中显然是明确的。
语句的子语句是以下内容之一: 对于选择语句,它的任何语句(但不是init-语句)
这意味着else后面的语句是主if-statement的子语句,接下来的规则是:stmt.stmt#stmt.pre-5
在任何子语句之外的选择语句或迭代语句中引入的名称从其声明点一直到语句子语句的结尾。这样的名称不能在任何子语句的最外层块中重新声明。
规则显然说,我们不能在这些子语句的最外层块中重新声明与声明的名称相同的名称。所以,我很好奇我是否误解了这些规则,还是草案中有一些缺陷?
发布于 2020-11-06 02:39:17
stmt.stmt#stmt.pre-5中的声明明确指出:
[注2:在任何子语句之外的选择语句或迭代语句中引入的名称范围从声明点到语句子语句的结尾。这样的名称不能在任何子语句(basic.scope.block)的最外层块中重新声明。-尾注]
这里的关键术语是在stmt.block#1中定义的最外层块
复合语句(也称为块)将语句序列分组为单个语句。 复合-声明: {语句-seq opt } ..。 复合语句定义块范围。
因此,stmt.stmt#stmt.pre-5本质上说:
if (int a = 0)
{ // outermost block
int a; // so ill-formed
} 但
if (int a = 0)
{ // outermost block
{ // inner block
int a; // so well-formed
}
} 在您的示例中,嵌套if语句引入的块也适用相同的规则。
发布于 2020-11-06 02:07:00
不是的。
您缺少了else子语句引入的块范围:
[stmt.selected.general/2]:selection语句中的子语句(每个子语句,以if语句的else形式表示)隐式定义块范围(basic.scope)。如果selection语句中的子语句是单个语句而不是复合语句,则就好像它被重写为包含原始子语句的复合语句。。。
也就是说,您的代码实际上是:
#include <iostream>
int main()
{
int b = 2;
if (int a = 0) {
}
else {
if (b == 2) {
int a;
}
}
}因此,您正在查看的块(由嵌套if引入的块)不是问题中的“最外层”块。因此,尽管a在该块中的作用域,但它可以被隐藏。
这确实意味着else,即:
#include <iostream>
int main()
{
int b = 2;
if (int a = 0) {
}
else {
int a;
}
}
/*
prog.cpp: In function ‘int main()’:
prog.cpp:9:9: error: redeclaration of ‘int a’
int a;
^
prog.cpp:6:11: note: ‘int a’ previously declared here
if (int a = 0) {
*/https://stackoverflow.com/questions/64707811
复制相似问题