C 正向声明类型-这背后的原因是什么

C 正向声明类型-这背后的原因是什么,c,C,你能解释一下转发声明背后的原因吗?这不是一个点的转发声明,这是一个typedef。typedef允许您编写 /* Forward declare a type "point" to be a struct. */ typedef struct point point; /* Declare the struct with integer members x, y */ struct point { int x; int y; }; 而不是 point p; 代码中未使

你能解释一下转发声明背后的原因吗?

这不是一个
点的转发声明,这是一个
typedef
typedef
允许您编写

/* Forward declare a type "point" to be a struct. */
typedef struct point point;
/* Declare the struct with integer members x, y */
struct point {
   int    x;
   int    y;
};
而不是

point p;
代码中未使用转发声明效果。但是,当
typedef
就位后,您可以开始在
结构的声明中使用
作为类型名称,而不是
结构
标记

实现相同效果的更常见方法是将定义和
typedef
组合起来,如下所示:

struct point p;
class C
{
  B b;
}
class B
{
  C c;
}
*typedef
恰好正向声明了类型,但这是一个“副作用”

vs

typedef的目的是从更基本的机器上形成复杂的类型 键入并为这些组合指定更简单的名称。他们是最 通常在标准声明很麻烦时使用,可能 容易混淆,或可能因实现而异

So
typedef结构点不是您假定的转发声明。它将
struct point
命名为
point
,这样当您稍后编写
point
时,它将引用
struct point


现在,您可以将变量声明为
点p而不是
结构点p

我注意到没有人真正回答你提出的问题,这是

转发声明类型的原因是什么

答案是:C的设计使它可以通过从上到下读取每个文件一次来编译。考虑C语言这样的语言:

请注意,如果编译器从上到下运行,则编译器在知道
B
是什么之前会到达
B
类型的字段。事实上,C#编译器不会从上到下一次读取整个文件。它对每个文件进行多次传递,在传递过程中积累信息

现在假设您想编写一个C#编译器,它可以在不进行多次传递的情况下解析上面的程序。不知何故,在遇到字段
b
之前,您必须告诉编译器有一个名为
b
的类型。但是我们不能把
B类
移到
C类
之前,因为这会再次产生同样的问题,这次是
C类

在我们想象的C#的单程版本中,你可能会说你可以像这样绕过这个问题:

struct point p;
class C
{
  B b;
}
class B
{
  C c;
}
就这样。当编译器到达
bb
时,它知道
bb
是一个稍后将定义的类<代码>B
已被转发声明

因为C#一直使用多通道方法,所以它不需要这种技巧。但是C的设计者确实希望采用单通道方法,因此他们需要前向声明的冗余

这种单通道方法的设计目的是使编译在当时更容易,当时机器只有几K内存,每秒运行几千个周期;相比之下,C#每次多次扫描构建复杂数据结构的方法成本高昂,而且在速度和内存受限的机器上很难实现


当然,现在我们的机器拥有数万亿字节的内存(请记住,内存就是磁盘空间;RAM只是磁盘上的缓存!),每秒运行数十亿个周期,但我们仍然不得不使用一些技术,使编译器编写者的生活在20世纪70年代变得更轻松。这就是使用C时的情况。

这不是一个转发声明,而是一个typedef。但是它与typedef struct point{}有何不同?在编译过程中,C编译器只知道它已经读入的内容。
typedef struct point
告诉编译器有一个名为
point
的类型(这就足够了)。@Theolodis,事实上它两者都是。在
typedef
中使用
struct point
是对
struct
类型的正向声明。作为回答,它并不完全正确。两者都是。在
typedef
中使用
struct point
是对
struct
类型的正向声明,作为回答不完全正确。两者都是。在typedef中使用struct point是结构的正向声明type@JensGustedt这正是我在脚注中所说的。你所说的“副作用”是什么意思?重要的是,这是一个转发声明,您只能声明已知类型的
typedef
s。从那时起,
point*
即使不知道
struct
@JensGustedt所说的“副作用”,我的意思是“它也会发生”。如果有人需要向前声明一个
struct
标记,他会写
struct点
并开始使用
struct point*
,而不知道
struct
的细节。当他想要“直接”效果时,就会发生这种情况。当有人编写
typedef
时,他希望它主要用于
typedef
,也就是说,当使用
struct point
时,能够删除
struct
。在
typedef
之后,编译器考虑声明的类型,并允许您使用
struct point*
,这是“次要”行为。
class C
{
  B b;
}
class B
{
  C c;
}
class B; // Tell the compiler that B will be defined later.
class C
{
  B b;
}
class B
{
  C c;
}