c-为什么结构指针的值错误



所以我开始研究C中的数据结构,并想编写一个Singly Linked List。

这是其中的一小部分:

struct nodes {
int val;
struct nodes *next;
};
void insert(struct nodes *list, int val) {
struct nodes *tmp = (struct nodes*) malloc(sizeof(struct nodes));
tmp->val = val;
tmp->next = list;
list = tmp;
}
int main() {
struct nodes *test;
insert(test, 5);
insert(test, 10);
printf("test %dn", test->next->val);
}

这里我得到了完全错误的输出。当我尝试编写一个不必传入结构指针的函数时,它的工作原理与预期的一样。

输出:

test 90053

p.S我仍然从C开始,所以不要判断得太难:D

您正在更改一个局部变量,这样就不会对调用方产生影响。你的意思可能是使用一个指针指向一个可以更改的指针:

int main() {
struct nodes *test = NULL; // Don't forget to initialize
insert(&test, 5);
insert(&test, 10);
printf("test %dn", test->next->val);
}

你的功能现在看起来像什么:

void insert(struct nodes **list, int val) {
struct nodes *tmp = malloc(sizeof(struct nodes)); // No need to cast malloc() in C
tmp->val = val;
tmp->next = *list;
*list = tmp;
}

由于list被取消引用(*list(,它实际上会更改原始值(指向的值(,这意味着您的列表头会更改。

在您的原始代码中,您从未初始化过list,它只是一些随机的垃圾值,并且由于insert永远无法更改它,因此它将保留为垃圾数据。通过它访问任何数据都是未定义的行为,所以你会得到垃圾数据或崩溃。

你可以走这条路:

struct nodes {
int val;
struct nodes* next;
};
nodes* insert(struct nodes* list, int val) {
struct nodes* tmp = (struct nodes*)malloc(sizeof(struct nodes));
tmp->val = val;
tmp->next = list;
return tmp;
}

当尝试这样的结构时,你写的第一个函数——我相信——是list((而不是insert((。

在每个可以更改列表起始地址的函数中,必须返回地址,否则地址将丢失。由于你只在开头插入,你就失去了一切,因为起始地址总是变化的。。一般情况下,不要使用void。至少是一种浪费,通常是一种错误。返回一些东西,比如完成状态。请参阅list()的实现,该实现返回。。。size

int         list(struct nodes* list)
{
struct nodes* p = list;
int N = 0;
while (p != NULL)
{
printf("#%d  %dn", N, p->val);
p = p->next; N += 1;
};
printf("n");
return N;
}

和使用2个函数的main((版本

int main() {
struct nodes* test = NULL;
int n = 0;
for(n = 800; n>0; n-= 100) test = insert(test, n);
n = list(test);
printf("At the end list() returned %dn", n);
}

通过这种方式,您可以从一开始就获得更多信息。

#0  100
#1  200
#2  300
#3  400
#4  500
#5  600
#6  700
#7  800
At the end list() returned 8

测试程序

#include <stdio.h>
#include <stdlib.h>
struct no
{
void*       item;
struct no*  next;
struct no*  prev;
};  // no
typedef struct no Node;
typedef struct
{
char* name;
unsigned  size;
unsigned  limit;
Node* start;
Node* end;
}   List;
struct nodes {
int val;
struct nodes* next;
};
struct nodes*   insert(struct nodes*, int);
int             list(struct nodes* L);
int main() {
struct nodes* test = NULL;
int n = 0;
for(n = 800; n>0; n-= 100) test = insert(test, n);
n = list(test);
printf("At the end list() returned %dn", n);
}
struct nodes*   insert(struct nodes* list, int val) {
struct nodes* tmp = (struct nodes*)malloc(sizeof(struct nodes));
tmp->val = val;
tmp->next = list;
return tmp;
}
int         list(struct nodes* list)
{
struct nodes* p = list;
int N = 0;
while (p != NULL)
{
printf("#%d  %dn", N, p->val);
p = p->next; N += 1;
};
printf("n");
return N;
}

正如评论中所指出的,请注意,列表不是node。一个列表,如果是节点的集合,并且节点具有数据负载。如果有效载荷是(void*),那么您就有了一个真正抽象的数据结构,因为它可以加载任何内容,从单个char100-fields structure

想想你写它的方式,以及你的程序中有5个列表的情况:它很快就会变成一团糟。并与下面的代码进行比较

链表结构

struct no
{
void*       item;
struct no*  next;
struct no*  prev;
};  // no
typedef struct no Node;
typedef struct
{
char* name;
unsigned  size;
unsigned  limit;
Node* start;
Node* end;
}   List;

注意,当你在List中输入更多信息时,事情会变得更容易:你总是有一个大小、一个限制、开始和结束的指针,等等

相关内容

  • 没有找到相关文章

最新更新