Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 结构上的差异?_C++_C_Data Structures - Fatal编程技术网

C++ 结构上的差异?

C++ 结构上的差异?,c++,c,data-structures,C++,C,Data Structures,这两者之间的区别是什么: typedef struct part { int a; } Part; 及 我知道第二个是“匿名”的,但它们不同吗?在这两种情况下,您都定义了一个结构类型,以及一个名为Part的类型别名,它引用了该类型 在第一种情况下,还定义了结构名部分< /> >,因此结构类型也可以被称为“代码>结构部分< /COD>,或者只是C++中的代码>部分。 在第二种情况下,结构本身没有名称(因此为“匿名”),只能由类型别名引用。由于该别名仅在结构定义之后声明,因此该结构不能引用

这两者之间的区别是什么:

typedef struct part 
{
   int a;
} Part;


我知道第二个是“匿名”的,但它们不同吗?

在这两种情况下,您都定义了一个结构类型,以及一个名为
Part
的类型别名,它引用了该类型

在第一种情况下,还定义了结构名<代码>部分< /> >,因此结构类型也可以被称为“代码>结构部分< /COD>,或者只是C++中的代码>部分。
在第二种情况下,结构本身没有名称(因此为“匿名”),只能由类型别名引用。由于该别名仅在结构定义之后声明,因此该结构不能引用自身。

除了Mike Seymour answer之外,下面是一个示例,说明原因:

例如链表

// this works
typedef struct part {
    struct part *next;
} Part;

// this doesn't work
typedef struct {
    struct Part *next;
} Part;
// neither this
typedef struct {
    Part *next;
} Part;

除了@EoiFirst的答案

typedef struct part 
{
   int a;
   struct part *next;
} Part;
这是有效的,因为
next
是指向
struct part
指针,因此它的大小与指针类型相同

C是一种类型化语言,因此编译器知道
next
的类型,在
struct part
完全定义之后,它将能够确定下面的代码是否有效。它知道
next
是一个指向
struct part
的指针,它有一个字段
inta

void test(struct part *p) {
    if (p != NULL && p->next != NULL) {
        printf("%d\n", p->next->a); // this is valid
    }
}
你可以申报

typedef struct part 
{
   int a;
   void *next;
} Part;
struct part
的大小仍然与上面声明的相同。现在
next
是指向任何东西的指针,上面带有
test()
的代码编译时会出错

warning: dereferencing 'void *' pointer
error: request for member 'a' in something not a structure or union
您需要编写
printf(“%d\n”,((struct part*)p->next)->a)

此外,您将无法申报此信息

typedef struct part 
{
   int a;
   struct part nested;
} Part;
您将得到一个编译器错误

error: field 'nested' has incomplete type

@MikeSeymur和其他人给出了很好的答案。我想补充一个没有人明确说明的要点

在大型项目中,重要的是尽量减少标题,并避免
#include
-在绝对必要的情况下隐藏其他标题

假设您的结构是在某个头文件
part.h
中定义的。定义的命名结构类型
Part
允许使用您的代码的其他人通过使用所谓的“转发声明”跳过#包括“Part.h”:

在匿名结构的情况下,文件foo.h被迫包含文件part.h

//file foo.h forced to #include part.h because "part" is typedef of anonymous type
#include "part.h"
void foo(part* p); 
在遗留代码中,这些匿名类型常常导致这样一种情况,即每个头都包含如此多的其他头,以至于维护和代码重用成为一场噩梦


一般来说,我建议不要使用匿名类型,除非您确切地知道自己在做什么(在很多情况下,它们完全可以,例如作为其他类型的实现成员)。

在第二种情况下,您将无法将该类型称为
结构部分
。当你做一个自引用(列表或树)数据结构时,差异是显著的,其中“代码>结构部分*子< /代码>必须是Stult.@ Selvay-Debug的一个成员。它也是有效的C++代码,而OP并没有说它们只关心C。这两个结构在运行时没有区别。如果这是你问题的主要要点。它们有不同的名称,与
struct A{}
struct B{}
有相同的区别,但是只要你能引用它,你为什么会在乎如何引用它呢?@dfg:你只能在结构定义中引用它(在
部分
声明之前)按结构名称-并且只有当它有一个时。为什么?做出这样的限制有什么意义?为什么不允许你自己引用它?@dfg:一般来说,你只能在声明名称后才能使用它们。这种限制的要点是允许在一个过程中解析程序,从而使编译比其他过程快得多。为什么?做出这样的限制有什么意义?为什么不允许你做第二件事呢?在第二个例子中,编译器怎么知道什么是Part(在第二个例子中)当它还没有定义时?但是当它的定义还没有完成时,编译器怎么知道
struct Part*next
是什么呢?@dfg编译器不需要知道类的定义,只要它知道它在那里。这就像向前声明某些东西一样。@dfg指针或引用不需要完整的类型定义。您只需要知道类型是否存在。
//file foo.h knows struct Part "by name only"
struct Part;
void foo(struct Part* p); //in pure C, works for C++ too
void bar(Part* p); //in C++
//file foo.h forced to #include part.h because "part" is typedef of anonymous type
#include "part.h"
void foo(part* p);