【问题标题】:Using a typedef as a variable name not generating any error使用 typedef 作为变量名不会产生任何错误
【发布时间】:2014-01-31 20:23:05
【问题描述】:

考虑到这种数据结构:

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

输出:http://ideone.com/wCxbjD

A (0.00, 1.00)
B (1.00, 0.00)
point = 7

【问题讨论】:

  • 第二个声明不是和typedef名称冲突吗?

标签: c++ c data-structures


【解决方案1】:

范围。

在外部范围(在您的情况下,在文件范围内,即在任何函数之外)声明的标识符可以在内部范围内(在您的情况下,在 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. */
}

输出是:

p = (10, 20), point = 42

如果我们修改上述程序,将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);
}

我们会得到一个错误; gcc 说:

c.c: In function ‘main’:
c.c:5:9: error: ‘point’ redeclared as different kind of symbol
c.c:3:34: note: previous declaration of ‘point’ was here

(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。
  • 我的印象是范围仅用于变量名称。我现在开悟了。
  • 这是一个很好的问题和答案,可以通过一些比 OP 显示的更多的好/坏示例受益。
  • @chux:我添加了一些例子。
【解决方案2】:

这显然是一个范围问题:

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

是合法的。

【讨论】:

    猜你喜欢
    • 2017-03-27
    • 2011-11-25
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    相关资源
    最近更新 更多