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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:02:55  来源:igfitidea点击:

Typedef struct in C Vs C++

c++cstructtypedef

提问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 *nextautomatically forward-declares a type called node. That then conflicts with your typedeftarget 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 nodecan 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 nodealready exists, no new type is forward-declared there … and since all you're then doing is renaming it in the same typedefstatement, C++ doesn't really care, knowing that it's all the same type (struct TisT; the difference is in syntax, not in name).

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

[C++11: 7.1.3/3]:In a given non-class scope, a typedefspecifier 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 typedefspecifier 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_tor struct node_tto 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_tstruct node_t引用此结构类型。如果声明的类型名称不存在,C++ 将在标签名称中搜索类型名称,因此不需要上述双重定义,但也无妨。

In both languages, the explicit struct node_tversion is required at any point before the type is completely defined, so any self-reference, and any forward references will use the structversion. I prefer this in header files, mostly because it reduces problems with order of #includedirectives.

在两种语言中,在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 ++头文件已被使用,它是不太可能很快消失),所以这是一个非常简单的方法,只是以任何一种语言工作。