与类型同名的变量放在函数、结构或类中时不会出现编译错误

Seb*_*hil 1 c++ gcc typedef visual-c++

鉴于代码:

#include <iostream>

typedef int Integer;
Integer Integer = 1234;

int main() {
    std::cout <<  "Integer: " << Integer;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc 11.2 编译器编译代码会导致编译错误:

error: 'Integer Integer' redeclared as different kind of entity
    4 | Integer Integer = 1234;
      |         ^~~~~~~

note: previous declaration 'typedef int Integer'
    3 | typedef int Integer;
      |             ^~~~~~~

In function 'int main()':
error: expected primary-expression before ';' token
    7 |         std::cout <<  "Integer: " << Integer;
      |                                             ^
Run Code Online (Sandbox Code Playgroud)

但是,将代码更改为:

error: 'Integer Integer' redeclared as different kind of entity
    4 | Integer Integer = 1234;
      |         ^~~~~~~

note: previous declaration 'typedef int Integer'
    3 | typedef int Integer;
      |             ^~~~~~~

In function 'int main()':
error: expected primary-expression before ';' token
    7 |         std::cout <<  "Integer: " << Integer;
      |                                             ^
Run Code Online (Sandbox Code Playgroud)

不会导致编译错误。
我尝试使用 gcc 11.2clang 12.0.1和 MSVC 19.29 编译器,第一个版本全部失败,但允许使用第二个版本。
为什么第二个版本可以工作而第一个版本却失败了?

Tho*_*mas 7

区别在于范围之一。

在第一个示例中,两个Integers 都在全局范围内声明:

typedef int Integer;
Integer Integer = 1234;
Run Code Online (Sandbox Code Playgroud)

在第二个示例中,一个是在全局范围中声明的,而另一个是本地范围内的main

typedef int Integer;
int main() {
    Integer Integer = 1234;
    ...
}
Run Code Online (Sandbox Code Playgroud)

它之所以有效,是因为当编译器读取第一个Integerinside时main,只有一个具有该名称的实体,因此它必须引用全局范围内的类型。但是一旦你声明了一个名为Integerinside的变量main,你就不能再次使用该名称来引用该类型:

typedef int Integer;
int main() {
    Integer Integer = 1234; // OK because only the type is visible.
    Integer otherInteger = 567; // Error because Integer is a variable here.
    ::Integer thirdInteger = 89; // OK because :: resolves to the global one.
}
Run Code Online (Sandbox Code Playgroud)