C++ 使用typedef作为变量名不会生成任何错误

C++ 使用typedef作为变量名不会生成任何错误,c++,c,data-structures,C++,C,Data Structures,考虑到这种数据结构: typedef struct { float x; float y; } point; 我用这个函数来排列坐标: point permute(point M) { point N; N.x = M.y; N.y = M.x; return N; } 为什么用名称(point)声明一个typedef的变量时没有给出任何错误 int main(void) { point A; point B; int point = 7;

考虑到这种数据结构:

typedef struct {
    float x;
    float y;
} point;
我用这个函数来排列坐标:

point permute(point M)
{
    point N;
    N.x = M.y;
    N.y = M.x;
    return N;
}
为什么用名称(
point
)声明一个
typedef
的变量时没有给出任何错误

int main(void)
{
point A;
point B;
int point = 7;

A.x = 0;
A.y = 1;
B = permute(A);

printf("A (%.2f, %.2f)\n", A.x, A.y);
printf("B (%.2f, %.2f)\n", B.x, B.y);
printf("point = %d\n", point);

return 0;
}
输出:

范围

在外部作用域中声明的标识符(在您的情况下,在文件作用域中,即在任何函数之外)可以在内部作用域中重新声明(在您的情况下,在
main
函数中)。内部声明将隐藏外部声明,直到到达内部范围的末尾

这通常适用于声明,而不仅仅是
typedef
名称

一个简单的例子:

#include <stdio.h>

typedef struct { int x, y; } point;

int main(void) {
    point p = { 10, 20 };
    /* p is of type point */

    int point = 42;
    /* This hides the typedef; the name "point"
       now refers to the variable */

    printf("p = (%d, %d), point = %d\n", p.x, p.y, point);
    /* p is still visible here; its type name "point" is not
       because it's hidden. */
}
如果我们修改了上述程序,将
typedef
移动到与变量声明相同的范围内:

#include <stdio.h>
int main(void) {
    typedef struct { int x, y; } point;
    point p = { 10, 20 };
    int point = 42;
    printf("p = (%d, %d), point = %d\n", p.x, p.y, point);
}
(C语言可以被定义为允许这样做,第二个声明
point
将第一个声明隐藏在范围的其余部分,但是设计人员显然认为从外部范围隐藏声明是有用的,但是在单个范围内这样做会导致更大的混乱。)

一个稍微复杂一点的例子:

#include <stdio.h>
int main(void) {
    typedef struct { int x, y; } point;
    { /* Create an inner scope */
        point p = { 10, 20 };
        /* Now the type name is hidden */
        int point = 42;
        printf("p = (%d, %d), point = %d\n", p.x, p.y, point);
    }
    /* We're outside the scope of `int point`, so the type name is
       visible again */

    point p2 = { 30, 40 };
    printf("p2 = (%d, %d)\n", p2.x, p2.y);
}
#包括
内部主(空){
typedef结构{intx,y;}点;
{/*创建一个内部作用域*/
点p={10,20};
/*现在类型名被隐藏*/
int点=42;
printf(“p=(%d,%d),点=%d\n”,p.x,p.y,点);
}
/*我们不在“int point”的范围内,因此类型名为
再次可见*/
点p2={30,40};
printf(“p2=(%d,%d)\n”,p2.x,p2.y);
}

这样的隐藏可能不是最好的主意;对两个不同的东西使用相同的名称,虽然对编译器来说没有问题,但可能会使人类读者感到困惑。但它允许您在块范围内使用名称,而不必担心您包含的所有标题可能在文件范围内引入的所有名称。`

这显然是一个范围问题:

typedef struct {
    float x;
    float y;
} point;

point point = {2.0, 3.0};
给出一个错误

blo.c:6:7: error: ‘point’ redeclared as different kind of symbol
point point = {2.0, 3.0};
      ^
blo.c:4:3: note: previous declaration of ‘point’ was here
 } point;
鉴于

void blo() {
  typedef struct {
    float x;
    float y;
  } point;

  {
    point point = {2.0, 3.0};
  }
}

是合法的。

第二个声明不是与typedef名称冲突吗?很有趣。我不知道你甚至可以在根作用域之外的任何地方声明typedef。我的印象是作用域只用于变量名。我现在开悟了。这是一个很好的问题和答案,比OP@chux展示的好/坏的例子更多。我添加了一些例子。
typedef struct {
    float x;
    float y;
} point;

point point = {2.0, 3.0};
blo.c:6:7: error: ‘point’ redeclared as different kind of symbol
point point = {2.0, 3.0};
      ^
blo.c:4:3: note: previous declaration of ‘point’ was here
 } point;
void blo() {
  typedef struct {
    float x;
    float y;
  } point;

  {
    point point = {2.0, 3.0};
  }
}