C 与 C++ 中的 Typedef 结构

Typedef struct in C Vs C++

这会在 C++ 中产生错误,但在 C 中不会:

typedef struct nodes
{
    int data;
    struct node *next;
}node;

它在 C++ 中给出以下错误。

/home/DS cpp/linkedlist.cpp|10|error: conflicting declaration ‘typedef struct nodes node’|
/home/DS cpp/linkedlist.cpp|9|error: ‘struct node’ has a previous declaration as ‘struct node’|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

为了在 C++ 中工作,我必须将其更改为:

typedef struct node
{
    int data;
    struct node *next;
}node;

我不明白为什么会这样,我想知道C和C++的执行顺序,以便我理解。

让我们稍微分析一下您的代码:

typedef struct nodes
{
    int data;
    struct node *next;
}node;

这声明并定义了 struct nodes,一个具有两个成员的类型,并声明了一个类型别名,因此我们只能将其称为 node

现在,在 C++ 中,成员声明 struct node *next automatically forward-declares a type called node。这会与您的 typedef 目标 node 发生冲突:就好像您试图为两种类型赋予相同的名称。

在C里是没有冲突的,因为叫node的类型其实只能指struct node.

第二个代码片段之所以有效,是因为在解析成员声明期间 struct node 已经存在,因此没有新的类型被前向声明……并且因为您随后所做的只是在同一个 typedef语句,C++并不关心,知道都是同一种类型(struct T T;区别在于语法,而不是名义上)。

[C++11: 7.1.3/3]: In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [ Example:

typedef struct s { / ... / } s;
typedef int I;
typedef int I;
typedef I I;

—end example ]

[C++11: 7.1.3/6]: In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type. [ Example:

class complex { / ... / };
typedef int complex; // error: redefinition

—end example ]

当然,在 C++ 中,这一切都没有实际意义,您应该只写:

struct node
{
   int data;
   node* next;
};

您不需要 typedef-away 详细类型说明符 struct.

你给出的C例子应该是错误的。您正在使用未使用 struct node.

定义的标签名称 (node)

鉴于这两个选择,第二个是要使用的。我更喜欢经济一点:

typedef struct node_t
{
    int data;
    struct node_t *next;
} node_t;

在C或C++中,标签名称有自己的命名空间,所以标签和typedef名称使用相同的名称是没有问题的。在 C 中,这允许您使用 node_tstruct node_t 来引用此结构类型。如果声明的类型名称不存在,C++ 将在标记名称中搜索类型名称,因此不需要上述双重定义,但不会造成伤害。

在这两种语言中,在完全定义类型之前的任何时候都需要显式 struct node_t 版本,因此任何自引用和任何前向引用都将使用 struct 版本。我更喜欢头文件中的这个,主要是因为它减少了 #include 指令顺序的问题。

PS:这 确实 在任何一种语言中都有效(请参阅 LRIO 对 C++11 标准的指针的回答)并且已被足够多的双语甚至双语使用纯 C++ 头文件,它不太可能很快消失)所以这是一种非常简单的方法,只适用于任何一种语言。