C V C++中的Typedef结构

Ach*_*ogi 18 c c++ struct typedef

这在C++中给出了错误,但在C中没有:

typedef struct nodes
{
    int data;
    struct node *next;
}node;
Run Code Online (Sandbox Code Playgroud)

它在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)) ===|
Run Code Online (Sandbox Code Playgroud)

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

typedef struct node
{
    int data;
    struct node *next;
}node;
Run Code Online (Sandbox Code Playgroud)

我不明白为什么会发生这种情况,我想知道C和C++中的执行顺序,以便我能理解它.

Lig*_*ica 25

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

typedef struct nodes
{
    int data;
    struct node *next;
}node;
Run Code Online (Sandbox Code Playgroud)

这声明并定义struct nodes了一个包含两个成员的类型,并声明了一个类型别名,因此我们只能将其引用为node.

现在,在C++中,成员声明struct node *next 自动向前声明一个名为的类型node.然后与你的typedef目标发生冲突node:就像你试图给两种类型的名字一样.

在C中,没有冲突,因为被调用的类型node实际上只能被称为struct node.

第二个片段起作用是因为,因为在成员声明的解析过程中struct node已经存在,没有新的类型在那里被前向声明...并且因为你所做的就是在同一个typedef语句中重命名它,C++并不真正关心,知道它是完全相同的类型(struct T 是 T ;区别在于语法,而不是名称).

[C++11: 7.1.3/3]:在给定的非类作用域中,typedef可以使用说明符重新定义在该作用域中声明的任何类型的名称,以引用它已引用的类型.[例如:

typedef struct s { / ... / } s;
typedef int I;
typedef int I;
typedef I I;
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

[C++11: 7.1.3/6]:在给定范围内,typedef不应使用说明符来重新定义在该范围中声明的任何类型的名称以引用不同的类型.[例如:

class complex { / ... / };
typedef int complex; // error: redefinition
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

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

struct node
{
   int data;
   node* next;
};
Run Code Online (Sandbox Code Playgroud)

你并不需要typedef-away的阐述类型说明符 struct.

  • 当你必须深入到1,338页的文档(库开始于第424页,所以语言部分只占整个文件的三分之一)只是回答关于名称和范围的基本问题时,你可以看到为什么有些人会想到C++太复杂了.:^) (12认同)
  • @MikeHosky:这太荒谬了 (2认同)
  • @LightnessRacesinOrbit:听起来确实如此.我还不得不提到Java 8语言规范是一个788页的PDF,这只是语言,没有平台API或VM规范.然而奇怪的是,没有人认为这会让Java过于复杂.我不认为可以同时以完整和简单的方式指定严肃的编程语言. (2认同)

Mik*_*sky 5

您提供的C示例应该是错误.您正在使用node尚未定义的标记名称()struct node.

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

typedef struct node_t
{
    int data;
    struct node_t *next;
} node_t;
Run Code Online (Sandbox Code Playgroud)

在C或C++中,标记名称具有自己的名称空间,因此对标记和typedef名称使用相同的名称没有问题.在C中,这允许您使用node_t或struct node_t引用此结构类型.如果声明的类型名称不存在,C++将在标记名称中搜索类型名称,因此不需要上面的双重定义,但不会受到影响.

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

PS:这确实工作在两种语言(见LRIO对指针到C++ 11标准答案),并在足够的双语甚至纯C++头文件已被使用,它是不太可能很快消失),所以这是一个非常简单的方法,只是适用于任何一种语言.

  • 另请注意POSIX [保留以__t`结尾的单词](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02)以供使用(作为类型名称); 在您自己的代码中使用约定不一定是个好主意. (5认同)
  • 开头的句子不正确; 代码是完全有效的,但非常非正统,C - 并且无疑是不符合预期的.`typedef`语句引入了三个类型名称; `struct nodes`(在语句末尾完成),`node`(`struct nodes`的同义词)和不完整类型`struct node`.这个不完整的类型与`struct nodes`是分开的; `struct nodes`类型只包含指向其他类型的指针.你不能使用`next`指针创建一个`nodes`列表而没有滥用的强制转换; `struct node`与`struct nodes`不同. (2认同)