显然,
出于 C 语言的起源,我们可以在同一作用域内同时声明一个结构体和一个非结构体,它们的名称相同。
例如:
struct Ambig {};
// the struct must be referred to with the prefix struct
void Ambig(struct Ambig* buf) {}
我只是好奇最初的原因是什么?如果不理解,这似乎是一个糟糕的语言设计示例,会导致歧义和混淆。
显然,
出于 C 语言的起源,我们可以在同一作用域内同时声明一个结构体和一个非结构体,它们的名称相同。
例如:
struct Ambig {};
// the struct must be referred to with the prefix struct
void Ambig(struct Ambig* buf) {}
我只是好奇最初的原因是什么?如果不理解,这似乎是一个糟糕的语言设计示例,会导致歧义和混淆。
正如Stroustrup所说,命名空间的历史原因是C语言中必须始终在结构体名称前加上struct
。 结构体的名称(例如联合或枚举的名称)被称为标签,并存在于与其他符号完全不同的名称空间中。 因此,像以下这样的事情:
struct stat
{
// ...
};
int stat( char const* filename, struct stat* buf );
完全合法。(以上实际上是 Posix 的一部分)。
在 C++ 中,一个类的名称(使用 class
、struct
或 union
声明)或枚举与其他所有内容位于同一命名空间中,并且与 C 不同,您可以编写以下内容:
struct MyClass {};
MyClass variableName;
struct MyClass variableName;
class
, struct
, union
或 enum
后跟一个符号)中,在查找中忽略非类型名称。struct X
和union Y
(C中没有class
关键字),或者使用typedef struct X A;
然后使用名称A
代替strcut X
(其中X和A可以是相同的名称)。X
是指struct X
。您不必在名称前面输入struct
、union
或class
,也不必使用typedef
创建一个新的独立名称。struct X
。这允许使用一个否则模糊的名称。struct stat
和一个函数 stat()
(它的第二个参数是一个 struct stat*
)。如果您想使用这个函数,就必须要有一个 struct stat
。 - James Kanzestruct tm
中,你有 tm_year
,而不仅仅是 year
。 - James KanzeC* cp; /*...*/ cp->memberOfD;
而追踪错误。不仅没有错误,甚至没有警告(除非使用了lint
)。 - James Kanzestruct
关键字不仅在C语言中是合法的,而且是必需的。此外,C接口(如Posix的接口)确实有名称相同的函数和结构体,因此在C++中必须这样做。这也是为什么它被允许的真正原因。 - James Kanze