为什么这不会给出重新声明错误?

Why doesn't this give redeclaration error?

本文关键字:声明 错误 新声明 为什么      更新时间:2023-10-16

我有这个代码-http://ideone.com/8Q8XIo

#include <stdio.h>
int xyz = 10;
int main(void) {
    int xyz = 20;//line 2
    printf("%d",xyz);
    return 0;
}

我的问题是-为什么它不给出重新声明错误?我知道第二次是在"主要"功能的范围内。但我认为只在"第2行"中执行xyz = 20是可以的,但不执行int xyz = 20

根据C标准(6.2.1标识符范围)

  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 );

在这种情况下,该标识符具有函数原型范围。此外,您甚至可以声明与名称相同的标签

In C

xyz:;
int xyz = 20;

或在C++中

xyz:
int xyz = 20;

同样在C中,标记也有自己的名称空间。因此,此声明在C 中有效

xyz:;
struct xyz
{
   int xyz;
};
int xyz = 20;

C作用域规则规定,当块内的声明命名了一个已经可见的标识符时,新声明会暂时隐藏旧声明,并且该标识符具有新的含义
在块的末尾,标识符恢复了原来的含义。

C11:6.2.1标识符的范围(p4):

[…]如果一个标识符指定两个同名的不同实体空间,作用域可能重叠。如果是,一个实体的作用域(内部作用域)将结束严格在其他实体的范围之前(外部范围在内部范围内标识符指定在内部范围中声明的实体;外部中声明的实体scope在内部scope内隐藏(不可见)

为什么它不给出重新声明错误?

因为这不是重新声明。您正在声明一个新的局部变量。由于它与全局作用域中的名称相同,所以它隐藏了,但仅此而已。它是完全合法的C.

它不会给出重新声明错误,因为它们位于不同的作用域中。第一个声明在全局范围内,第二个声明在本地范围内(仅在main中有效)。

为什么它不给出重新声明错误?

因为(正如其他人所说)虽然这是一个重新声明,但只要这两个变量在不同的范围内,就不是错误情况。

差异:

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
}