【问题标题】:Linked list: Should the type of pointer "next" and the name of struct be same?链表:指针“next”的类型和结构的名称应该相同吗?
【发布时间】:2017-11-10 05:52:29
【问题描述】:
#include<stdio.h>
#include<stdlib.h>
typedef struct {
    int val;
    struct node* next;
} Node, *NodePtr;
void makeInitialLinkedList(int a[], int n)
{
    int i;
    NodePtr rec=NULL;
    NodePtr head=NULL;
    for (i=0; i<n; i++) {
        NodePtr cur=(NodePtr)malloc(sizeof(Node));
        if (i==0) head=cur;
        if (rec!=NULL) rec->next=(node*)cur;
        cur->val=a[i];
        cur->next=NULL;
        rec=cur;
    }

    // test
    while(n--) {
        printf("%d ", head->val);
        head=(NodePtr)head->next;
    }
}
NodePtr copy(NodePtr head)
{
    return NULL;
}
int main()
{
    //Mission #2
    int initialDataArray[10]={5,3,2,8,9,7,0,6,4,1};
    makeInitialLinkedList(initialDataArray, 10);

}

我不明白为什么会这样。我最初没有为结构命名,只通过 typedef 命名了姓氏“Node”。那么“struct node* next”是如何正常工作的呢? node* 是一种像 int* 或 char* 这样的数据类型吗?我是这样想的:

typedef struct strName {
    int val;
    struct strName* next;
} strSurName, *strPtr;

指针“next”的类型和struct的初始名称是否必须相同?

【问题讨论】:

  • 总的来说,我相信拥有相同的类型是好的,但这取决于你。它也可以是void * 类型
  • 不要为了获得语法糖而将指针语义隐藏在 typedef 后面。
  • typedef 指针不是一个好习惯;这可能会导致错误和混乱。
  • 我知道这不好,但我的愚蠢教授坚持这样......哈哈
  • “我不明白为什么会这样。” - 你发布的代码确实编译 - 因为node没有像你想象的那样定义

标签: c pointers struct linked-list typedef


【解决方案1】:

使用struct node* next 作为(未命名的)结构的成员,您实际上做了两件事 - 前向声明一个结构 struct node 并定义一个名为 next 的成员作为指向(前向声明的)struct node 的指针.请注意,struct node,因为它刚刚被前向声明,是不完整的,并且是一个 additinal, new 结构,与您实际想要引用的封闭结构不同。也授予struct forward declaration at cppreference

以下形式的声明 struct name; 隐藏任何 标记名称空间中名称名称的先前声明的含义 并将 name 声明为当前范围内的新结构名称,这将是 后定义。在定义出现之前,此结构名称具有 不完整的类型。这允许结构相互引用:

struct y;
struct x { struct y *p; /* ... */ };
struct y { struct x *q; /* ... */ };

所以它只是 似乎 好像您有一个指向您正在定义的 struct 的指针,但实际上您是(前向声明)并使用一个新结构。请参阅以下示例,该示例实际编译。

struct known_struct {
    int a[20];
};

struct own_struct {
    int val;
    struct known_struct* known;
    struct own_struct *own;
    struct unknown_struct* unknown;
} test;

int main(){

    size_t sizeOfKnownMember = sizeof(*(test.known));  // gives 80
    size_t sizeOfMemberOwn = sizeof(*(test.own));  // gives 32
    // size_t sizeOfunknownMember = sizeof(*(test.unknown));  // invalid application of sizeof to incomplete type `struct unknown_struct`

    return 0;
}

【讨论】:

  • 你是对的。它之所以有效,是因为 next 是一个指针,而您实际上从未取消引用它。只有地址被传递和操作(实际上并不需要node 是完整的)。如果您实际上尝试打印next-&gt;val,那么您将看到出现问题的原因,此时编译器需要知道仅前向声明的node 的大小。很好的答案。
【解决方案2】:

我不明白为什么会这样。

没有,你应该得到编译错误,比如 gcc 6.3 或 4.2.1:

prog.c: In function ‘makeInitialLinkedList’:
prog.c:15:35: error: ‘node’ undeclared (first use in this function)
         if (rec!=NULL) rec->next=(node*)cur;
                                   ^~~~
prog.c:15:35: note: each undeclared identifier is reported only once for each function it appears in
prog.c:15:40: error: expected expression before ‘)’ token
         if (rec!=NULL) rec->next=(node*)cur;
                                        ^

Live demo 来自 Deduplicator。

node* 是 int* 还是 char* 这样的数据类型吗?

没有。除非您自己定义node,否则您所拥有的将导致错误。

指针“next”的类型和struct的初始名称是否必须相同?

就是这样。

【讨论】:

  • 这在 dev c++ 编译器上运行
  • @keist99 查看 Coliru 上的错误:coliru.stacked-crooked.com/a/3512293b47e95856
  • @keist99 那是一个旧的编译器。在线尝试代码,例如在 Ideone 中,会出错!重复数据删除器很好,如果您不介意,我将在我的答案中注入此链接。 =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-03-30
  • 2012-11-27
  • 1970-01-01
相关资源
最近更新 更多