C Vs C++ 中的 Typedef 结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31903594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typedef struct in C Vs C++
提问by Achyut Rastogi
This gives an error in C++ but not in C:
这在 C++ 中给出了一个错误,但在 C 中没有:
typedef struct nodes
{
int data;
struct node *next;
}node;
It gives the following error in C++.
它在 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)) ===|
For it to work in C++ I have to change it to this:
为了让它在 C++ 中工作,我必须将其更改为:
typedef struct node
{
int data;
struct node *next;
}node;
I don't understand why this happens, I want to know the order of execution in both C and C++ so that I can understand it.
我不明白为什么会发生这种情况,我想知道 C 和 C++ 中的执行顺序,以便我可以理解它。
回答by Lightness Races in Orbit
Let's analyse your code a bit:
让我们稍微分析一下您的代码:
typedef struct nodes
{
int data;
struct node *next;
}node;
This declares and defines struct nodes
, a type with two members, and declares a type alias so we can refer to it only as node
.
这声明并定义struct nodes
了一个具有两个成员的类型,并声明了一个类型别名,因此我们只能将其称为node
.
Now, in C++, the member declaration struct node *next
automatically forward-declares a type called node
. That then conflicts with your typedef
target node
: it's as if you're trying to give two types the same name.
现在,在 C++ 中,成员声明会struct node *next
自动向前声明一个名为node
. 然后与您的typedef
目标冲突node
:就好像您试图为两种类型提供相同的名称。
In C, there is no conflict, because the type called node
can in fact only be referred to as struct node
.
在 C 中,没有冲突,因为调用的类型node
实际上只能称为struct node
。
The second snippet worked because, since during parsing of the member declaration struct node
already exists, no new type is forward-declared there … and since all you're then doing is renaming it in the same typedef
statement, C++ doesn't really care, knowing that it's all the same type (struct T
isT
; the difference is in syntax, not in name).
第二个片段有效,因为在成员声明的解析过程中struct node
已经存在,没有新类型在那里进行前向声明......并且因为你所做的只是在同一个typedef
语句中重命名它,C++并不真正关心,知道它们都是相同的类型(struct T
是T
;区别在于语法,而不是名称)。
[C++11: 7.1.3/3]:
In a given non-class scope, atypedef
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, atypedef
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++11: 7.1.3/3]:
在给定的非类作用域中,typedef
可以使用说明符重新定义在该作用域中声明的任何类型的名称,以引用它已经引用的类型。[ 例子:typedef struct s { / ... / } s; typedef int I; typedef int I; typedef I I;
—结束示例]
[C++11: 7.1.3/6]:
在给定的范围内,typedef
不应使用说明符重新定义在该范围内声明的任何类型的名称以引用不同的类型。[ 例子:class complex { / ... / }; typedef int complex; // error: redefinition
—结束示例]
Of course, in C++, this is all moot and you should just write:
当然,在 C++ 中,这一切都没有实际意义,你应该只写:
struct node
{
int data;
node* next;
};
You do not need to typedef
-away the elaborated-type-specifierstruct
.
您不需要typedef
-away详细类型说明符struct
。
回答by Mike Housky
The C example you gave should be an error. You're using a tag name (node
) that you haven't defined with struct node
.
您给出的 C 示例应该是错误的。您正在使用node
尚未定义的标记名称 ( ) struct node
。
Given those two choices, the second is the one to use. I prefer a bit of economy:
鉴于这两个选择,第二个是要使用的。我更喜欢经济一点:
typedef struct node_t
{
int data;
struct node_t *next;
} node_t;
In C or C++, the tag names have their own namespace, so there is no problem with using the same name for the tag and the typedef name. In C, this allows you to use either node_t
or struct node_t
to refer to this struct type. C++ will search the tag names for a type name if a declared type name doesn't exist, so the above double-definition isn't needed, but doesn't hurt.
在 C 或 C++ 中,标签名称有自己的命名空间,因此标签名称和 typedef 名称使用相同的名称没有问题。在 C 中,这允许您使用node_t
或struct node_t
引用此结构类型。如果声明的类型名称不存在,C++ 将在标签名称中搜索类型名称,因此不需要上述双重定义,但也无妨。
In both languages, the explicit struct node_t
version is required at any point before the type is completely defined, so any self-reference, and any forward references will use the struct
version. I prefer this in header files, mostly because it reduces problems with order of #include
directives.
在两种语言中,在struct node_t
类型完全定义之前的任何时候都需要显式版本,因此任何自引用和任何前向引用都将使用该struct
版本。我更喜欢在头文件中使用它,主要是因为它减少了#include
指令顺序的问题。
PS: This doeswork in either language (see LRIO's answer for pointers into the C++11 Standard) and has been used in enough bilingual and even pure C++ header files that it's unlikely to disappear soon) so it's a very simple approach that just works in either language.
PS:这确实工作在两种语言(见LRIO对指针到C ++ 11标准答案),并在足够的双语甚至纯C ++头文件已被使用,它是不太可能很快消失),所以这是一个非常简单的方法,只是以任何一种语言工作。