1

给定以下代码:

typedef struct elementT {
  int data;
  struct elementT *next;
} element;

为什么有必要做struct elementT *next而我不能element *next在结构声明本身内部做?是因为还没有申报吗?

4

4 回答 4

3

typedef唯一发生在定义之后struct。考虑以下代码;语法无效,但它希望它显示事物的顺序/优先级:

typedef (struct {
  int field1, field2;
}) item;

即,struct{...}是表示类型的“表达式”。通过typedef给它一个名字来操作那个类型。

相比之下,

struct foo {
    foo *next;
};

之所以起作用,是因为 C 的两个特殊规则:struct <name>不仅定义了一个类型,而且还给它一个struct标签,并且该标签在struct声明的其余部分中立即可见(出于显而易见的原因:链表、树等将是如果没有这些规则,实施起来非常痛苦)。

于 2013-01-14T21:26:48.283 回答
2

因为C是这么说的:

(C99,6.2.1p7)“[...] 任何其他标识符的范围都在其声明符完成后开始。”

于 2013-01-14T21:26:41.933 回答
2

nameelementT是类型 name 的一部分,struct elementT一旦编译器看到这两个标记,就会变得可见(作为不完整的类型)struct elementT,因此您可以将其用作结构定义中的类型名称。

name是一个 typedef 名称,在标识符出现element之前不可见,标识符出现在结构定义的结尾(结束)之后;因此你不能在结构定义中使用它,只是因为它还不存在。element}

我个人的偏好(很多非常聪明的人在这一点上与我不同)根本不使用typedef。该类型已经有一个很好的名字,struct ElementT; 为什么要添加第二个?我只想写:

struct element {
    int data;
    struct element *next;
};

并将类型称为struct element

如果您觉得为类型使用一个单词名称就足够有用了,当然,您仍然可以使用 typedef。请记住,typedef 名称直到声明结束后才可见。并且不需要使用两个不同的标识符:

typedef struct element {
    int data;
    struct element *next;
} element;

现在您可以将类型称为 asstruct element或 as element

(请注意,C++ 有不同的规则;它有效地为struct(or union, class, or enum) 类型创建了一个隐式 typedef。在 C++ 中,这typedef是不必要的但无害的。)

于 2013-01-14T21:30:42.383 回答
1

如果将结构声明与其定义分开,则可以实现此行为:

struct ElementT;                   // not strictly needed

typedef struct ElementT element;   // this declares "struct ElementT" as well

struct ElementT
{
    element * next;
};
于 2013-01-14T21:29:06.367 回答