在定义结构之前如何使用指向结构的指针?

时间:2016-04-11 15:46:38

标签: c++ c memory memory-management struct

我很难理解这段代码是如何工作的。我总是在使用指向结构的指针之前想到它应该被定义。在下面的例子中,为什么编译器不抱怨struct LL * Next?

typedef struct LL
{
    int value;
    **struct LL* Next;**
}Node;

Node* temp;

3 个答案:

答案 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;
}