我很难理解这段代码:
typedef struct node
{
int data;
struct node * next;
} node;
typedef node * nodepointer;
所以,我们正在使用typedef构建struct节点...我假设我们这样做是为了初始化struct而不需要“struct”关键字。
我想问为什么在结构定义中我们使用名称“node”两次(在开始和结束时)。
其次typedef node * nodepointer;
指向的是什么。在这种情况下是否有必要使用typedef?这个表达式node * nodepointer;
不相等吗?
答案 0 :(得分:4)
首先,让我们在这里说清楚:typedef
不是变量的声明。它只是将新类型 name 别名为现有类型说明符。
typedef <type specifier> new_type_name;
所以,这里发生的事情当然可以欺骗未经训练的人。
struct node
本身是名为struct
的{{1}},其中包含两个属性node
和一个int data
。
我稍后会更多地进入struct node *next
,但现在这很简单。
然后,周围的next
接受该结构并为其命名typedef
。为什么这样,你可能会问?
这是因为在C(与C ++不同)中,tag name使用结构需要在类型前加上node
。
struct
使用typedef,我们使用名为struct Foo {
// ...
};
Foo bar; // ERROR
struct Foo bar; // OK
的 typename 为结构命名。这个例子应该让它更清晰。
node
请记住,您可以定义没有标签的结构,因此typedef struct Foo {
// ...
} FooType;
Foo bar; // ERROR
struct Foo bar; // OK
FooType bar; // OK
struct FooType bar; // ERROR
可以定义结构。
typedef
虽然我会在你的例子中解释为什么你无法这样做。
示例中的属性typedef struct {
// ...
} FooType;
FooType bar; // OK
是incomplete type。不完整的类型,简单地说,是声明的类型(给定名称和类型,即struct node *next
),但不是定义(给定&# 39;身体&#39;,即struct node;
)。
不完整的类型在定义之前无法使用,除非您指向 。
struct node { int foo; };
因此,声明类型为struct Foo;
struct Foo bar; // ERROR: Foo is not defined.
struct Foo *bar; // OK - it's just a pointer. We know the size of a pointer.
struct Foo {
// ...
};
struct Foo bar; // OK - it's defined now.
时,我们已经拥有struct node *next
的声明,而不是定义,它会指向struct node
可能。
您也可以推断,直接使用struct node
会不工作:
struct node
回答你的最后三个问题:
struct node { struct node next; // ERROR - `struct node` becomes infinitely big struct node *next; // OK - a pointer is usually 4/8 bytes (we at least know its size at this point) };
[指向] [?]
无。它只是别名(标签或昵称&#39;)到另一种类型。它只是说类型typedef node * nodepointer;
实际上是nodepointer
。
这也意味着任何需要node *
的内容都可以使用node *
,反之亦然。
在这种情况下是否有必要使用
nodepointer
?
没必要,没有。您也可以在任何地方使用typedef
而不是node *
。大多数编码标准对nodepointer
类型的指针类型(如您的示例)不屑一顾,因为它会增加代码库的混淆(正如您在此问题中所证明的那样!:))
表达式
typedef
不相等吗?
不。同样,请记住node * nodepointer;
只是指定引用相同类型的另一种方式。它实际上并没有创建任何内存,而是为现有类型提供一个新名称。
答案 1 :(得分:3)
这个结构是自引用的,这意味着它包含一个指向自身的指针。
如果您不使用标记node
,您将如何在以后指定指针类型。因此,首先需要node
struct node {
struct node *ptr;
};
// you can do this way too
typdef struct node node;
完成node
需要最后typedef
。
按typedef node * nodepointer;
,现在您可以使用nodepointer
表示node*
。无论node*
出现在何处,您只需替换为nodepointer
在这种情况下是否有必要使用typedef?
由你决定,
这个表达式是node * nodepointer;不相等?
不,这只声明nodepointer
是指针变量,而typedef
通过名称创建别名,node *
nodepointer
。
答案 2 :(得分:1)
typedef struct node
int data;
struct node * next;
} node;
第一行中的node
是结构的标记。
最后一行中的node
是该类型的名称。
这两者不必相同。
如果您希望它们不同,代码将如下所示。
typedef struct helloNode
int data;
struct helloNode * next;
} node;
类型名称为node
。结构的名称是helloNode
有关更具技术性的解释,这两个nodes
位于不同的命名空间中。并且可以有不同的价值观。
来自http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
的第6.3节如果在a中的任何一点可以看到多个特定标识符的声明 在翻译单元中,句法上下文消除了引用不同实体的用法。 因此,各种标识符类别都有单独的名称空间,如下所示:
- 标签名称(通过标签声明和使用的语法消除歧义);
- 结构,联合和枚举的标记(通过跟随any32消除歧义) 关键字struct,union或enum);
- 结构或工会的成员;每个结构或联合都有一个单独的名称 其成员的空间(通过用于访问的表达式的类型消除歧义 会员通过。或 - &gt;操作者);
- 所有其他标识符,称为普通标识符(在普通声明符中声明或作为 枚举常量)。
答案 3 :(得分:1)
问题是你一次做两件事:声明结构类型并将该结构定义为名称。
对于typedef
,语法为
typedef <some type> name;
其中某些类型可能是简单类型,例如int
,long
等,也可能是struct foo
之类的复杂类型,而且无论是struct foo
还是typedef struct foo { int bar; } foo;
都是如此之前宣布或在此时宣布。
所以
typedef <some type> name;
对应
<some type>
其中struct foo { int bar; }
为name
且foo
为<some type>
至于第二个问题,
在这种情况下,node *
为name
而nodepointer
为typedef node * nodepointer;
,所以
nodepointer
键入node
作为指向struct node { ... }
的指针(您之前已将typedefd设为public class MainClass{
public static void main(String[] args) {
String out="";
String Format="0000.0000";
DecimalFormat dfm=new DecimalFormat(Format);
out=dfm.format(123.45);
System.out.println("out="+out);
}
}
)
答案 4 :(得分:0)
Daleisha正确地说你需要struct标签才能声明指向这些结构的指针next
。在引入之前,您无法写下该类型名称。另一种可能性是前向声明结构:
struct node;
typedef struct node node;
struct node
{
node *next;
int i;
};
但是,这引入了更多关于node
或其他{。}}的提及。
作为一个副作用,引入struct标签“node”使得仍然可以编写普通的struct node
,而单独的typedef是不可能的。
第二个typedef仍然是typedef,它不会引入变量而是引入类型名称。完成源代码段中的所有声明后,您可以说
struct node *np1;
node *np1;
nodepointer np1;
这些都是等效的。
两个类型名node
和struct node
的共存是可能的,因为它们被称为“struct tags”(如“struct node”中的“node”)与其他名称分开,因此可以用来命名别的东西,另外,没有碰撞。要键入一个结构,以便新类型具有struct标签的名称是一个常见的例子,但名称“node”可以用于其他任何东西(int变量,无论如何)。
答案 5 :(得分:0)
对于struct,您要定义结构名称(在大括号之前),然后是类型名称(在大括号之后):
typedef struct node {
int data;
struct node* next;
} node;
下一个创建另一个类型,指向节点的指针:
typedef node* nodepointer;
现在都可以用来创建变量:
node myNode;
nodepointer aPtr;