6

我遇到了一些代码阅读

typedef enum eEnum { c1, c2 } tagEnum;

typedef struct { int i; double d; } tagMyStruct;

我听说这些结构源自 C。在 C++ 中,您可以轻松编写

enum eEnum { c1, c2 };
struct MyStruct { int i; double d; };

真的吗?你什么时候需要第一个变种?

4

5 回答 5

11

首先,这两种声明在 C 和 C++ 中都是合法的。但是,在 C 中,它们的语义略有不同。(特别是,您稍后引用该结构的方式会有所不同)。

要理解的关键概念是,在 C 中,结构存在于单独的命名空间中。所有内置类型以及 typedef 都存在于“默认”命名空间中。也就是说,当我键入时int,编译器只检查这个“默认”命名空间。如果我在您的示例中键入“tagMyStruct”,编译器也只检查这个命名空间。但根据您使用的声明类型,该名称空间中可能不存在该结构。

结构是不同的,存在于单独的命名空间中。因此,如果我做出以下声明:

struct mystruct {};

不能简单地将其称为 mystruct。相反,我必须指定我想要 struct 命名空间中存在的 mystruct:

void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter

从长远来看,这有点冗长和尴尬。相反,您可以将其 typedef 到默认命名空间中:

typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace

现在,我的函数可以以直接的方式声明:

void foo(mystruct bar);

因此,您的第一个示例只是将这两个步骤合并在一起:声明一个结构,并将别名放入常规命名空间。当然,由于我们无论如何都要对它进行类型定义,我们不需要“原始”名称,因此我们可以使结构匿名。所以在你的声明之后

typedef struct { int i; double d; } tagMyStruct;

我们有一个没有名称的结构,它在默认命名空间中已被类型定义为“tagMyStruct”。

C就是这样对待它的。这两种类型的声明都是有效的,但一种不会在“默认”命名空间中创建别名,因此每次引用该类型时都必须使用 struct 关键字。

在 C++ 中,不存在单独的 struct 命名空间,因此它们的含义相同。(但首选较短的版本)。

编辑为了清楚起见,不,C 没有名称空间。不是通常意义上的。C 只是将标识符放入两个预定义的命名空间之一。结构(和枚举,我记得)的名称放在一个中,所有其他标识符放在另一个中。从技术上讲,这些是命名空间,因为它们是单独的“容器”,其中放置名称以避免冲突,但它们肯定不是 C++/C# 意义上的命名空间。

于 2009-02-05T16:16:37.797 回答
10

在 C 中,如果你要写

struct MyStruct { int i; double d; };

每当您想引用该类型时,您都必须指定您正在谈论的是一个结构:

struct MyStruct instanceOfMyStruct;
struct MyStruct *ptrToMyStruct;

使用 typedef 版本:

typedef struct { int i; double d; } tagMyStruct;

你只需要写:

tagMyStruct instanceOfMyStruct;
tagMyStruct *ptrToMyStruct;

typedef 版本的另一大优势是您可以在 C 和 C++ 中以相同的方式引用结构,而在第二个版本中,它们在 C 中的引用方式与在 C++ 中的不同。

于 2009-02-05T15:42:16.180 回答
1

这只是简写。

在第二种情况下,要声明您将使用的结构:

struct MyStruct a;

在第一个变体中,您可以这样做:

tagMyStruct a;
于 2009-02-05T15:37:20.450 回答
0

第二种变体也存在于 C 中。

每当您想命名您的类型时,您都可以使用第一个变体,例如:

tagEnum myFunc(tagMyStruct * myArg);
于 2009-02-05T15:39:29.883 回答
0

第一个在 C++ 中可能不方便,因为您不能在头文件中转发声明它。

于 2009-02-05T15:42:11.343 回答