我很难理解这段代码是如何工作的。我总是在使用指向结构的指针之前想到它应该被定义。在下面的例子中,为什么编译器不抱怨struct LL * Next?
typedef struct LL
{
int value;
**struct LL* Next;**
}Node;
Node* temp;
答案 0 :(得分:5)
在您的代码中,
struct LL* Next;
被允许作为struct LL
定义本身内的成员,并且不会抛出任何错误,因为在那时,编译器不需要知道结构本身的定义。它只需要分配一个指向结构的指针,因此它可以。
稍后,在使用struct
类型的变量时,您必须为指针对象分配内存,并在进一步使用之前将该内存分配给指针。
答案 1 :(得分:0)
您可以在结构定义中使用不完整的类型(缺少足够的信息来确定该类型的对象的大小)。当您在struct LL* Next;
的定义中编写struct LL
时,LL
已经被声明为结构,因此不会抛出任何错误。
事实上,N1570提供了一些例子:
10示例1此机制允许声明自引用 结构
struct tnode { int count; struct tnode *left, *right; };
指定包含整数和两个指针的结构 相同类型的对象。 ......
11以下替代公式使用typedef机制:
typedef struct tnode TNODE; struct tnode { int count; TNODE *left, *right; }; TNODE s, *sp;
答案 2 :(得分:-1)
"应始终初始化变量"是一个经验法则。它不是一个伟大的规则,有时(就像你的例子中),它必须被违反,至少是暂时的。未初始化的数据(垃圾)本身不会引起问题。
有些程序员会虔诚地将这些变量初始化。
int i = 0;
Node * foo = NULL;
没有什么能迫使你这样做。只是程序员做了不必要的事情。
在取消引用它们之前初始化指向有意义的内容 非常重要。
#include <stdio.h>
#include <stdlib.h>
typedef struct LL
{
int value;
struct LL* next;
}Node;
int main (int argc, char ** argv)
{
Node * A; // OK. A points at garbage.
Node * B; // OK. B points at garbage.
B = A; // Dumb, but OK. B now points at the same garbage as A.
B = A->next; // ERROR. You can't dereference garbage.
A = malloc (sizeof(Node)); // A is no longer points at garbage. The newly created A->value and A->Next are garbage though.
B = A->next; // Dumb, but OK. B now points at the same garbage as A->Next.
B->value = 200; // ERROR. B is garbage, you can't dereference garbage.
A->value = 100; // OK. A->value was garbage, but is now 100.
// *********************************
// Enough academic examples. Let's finish making the linked list.
A->next = malloc(sizeof(Node)); // OK. A->value no longer points at garbage.
B = A->next; // OK. B now points at the second node in the list.
B->value = 200; // OK. B->value was garbage, is now 200.
B->next = NULL; // OK. B->Next was garbage, is now NULL.
printf("A: %#x, value: %d, next: %#x\n", A, A->value, A->next);
printf("B: %#x, value: %d, next: %#x\n", B, B->value, B->next);
return 0;
}