我有这段代码 - http://ideone.com/8Q8XIo
#include <stdio.h>
int xyz = 10;
int main(void) {
int xyz = 20;//line 2
printf("%d",xyz);
return 0;
}
我的问题是 - 为什么不给出重新声明错误?我知道第二次它在'main'函数的范围内。但我认为在'第2行'中只做xyz = 20
就可以了,但不是int xyz = 20
。
答案 0 :(得分:4)
C范围规则表示,当块内的声明命名已经可见的标识符时,新声明会暂时隐藏旧声明,并且标识符具有新含义。
在块的末尾,标识符重新获得其旧的含义。
[...]如果标识符指定同名的两个不同实体 空间,范围可能重叠。如果是这样,一个实体的范围(内部范围)将结束 严格地在另一个实体的范围之前(外部范围)。 在内部范围内, identifier指定在内部作用域中声明的实体;在外部宣布的实体 范围隐藏(并且在内部范围内不可见)。
答案 1 :(得分:4)
根据C标准(6.2.1标识符范围)
- ...在内部范围内,标识符指定声明的实体 在内在范围内;在外部作用域中声明的实体是隐藏的 (并且在内部范围内不可见)。
醇>
在您的示例中,第一个声明的标识符
int xyz = 10;
有文件范围。第二个声明的标识符
int xyz = 20;//line 2
具有包含在文件范围内的块范围。也就是说,块作用域是相对于文件作用域的内部作用域。第二个声明的标识符隐藏块范围内的第一个声明的标识符。
同样适用于C ++。只有C ++具有名称空间并使用限定名称,您可以访问隐藏的变量。例如
#include <iostream>
int xyz = 10;
int main() {
int xyz = 20;//line 2
std::cout << "xyz = " << xyz << ", ::xyz = " << ::xyz << std::endl;
return 0;
}
::
之前的xyz
表示全局命名空间。
考虑到您还可以在函数声明中使用相同的名称作为函数参数声明。例如
void f( int xyz );
在这种情况下,此标识符具有函数原型范围。你甚至可以声明一个与例如
同名的标签在C
xyz:;
int xyz = 20;
或在C ++中
xyz:
int xyz = 20;
同样在C标签中有自己的命名空间。所以这个声明在C
中有效xyz:;
struct xyz
{
int xyz;
};
int xyz = 20;
答案 2 :(得分:2)
为什么不给出重新声明错误?
因为它不是重新声明。您正在声明一个新的局部变量。由于它与全局范围中的名称相同,因此它隐藏那个,但那就是它。这是完全合法的C.
答案 3 :(得分:1)
它没有给出重新声明错误,因为它们位于不同的范围内。第一个声明在全局范围内,第二个声明在本地范围内(仅在main中有效)。
答案 4 :(得分:0)
为什么不给出重新声明错误?
因为(正如其他人所说)虽然这是重新声明,但只要两个变量在不同的范围内,它就不是错误的情况。
差异:
int f() {
int x = 0;
int x = 1; // same scope, this will not compile (redeclaration error)
}
int g() {
int x = 0;
{
int x = 1; // inner scope, no conflict at all
std::cout << x << "\n"; // print 1
}
std::cout << x << "\n"; // print 0
}