我正在尝试在c:中实现节点列表
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
void *next;
} node_t;
void printlist(node_t*head){
for(node_t*i=head;i;i=i->next)
printf("%in",i->value);
}
node_t create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return *ret;
}
int main(){
int i=0;
node_t*head=0;
for(node_t*tmp;i++<10;head=tmp)
{
*tmp=create(i+100);
tmp->next=head;
}
printlist(head);
}
在for循环中,我使用node_t*指针,该指针被分配给create
函数外部的已初始化(通过malloc
(结构。但程序发出:
warning: ‘tmp’ may be used uninitialized in this function [-Wmaybe-uninitialized]
*tmp=create(i+100);
Command terminated
那么,如何为c中已经初始化的数据分配一个取消引用的指针呢?
当您第一次进入循环时,tmp
不指向任何东西。因此,取消引用指针是无效的。
此外,create
中存在内存泄漏。您为一个节点动态分配内存,但随后返回该节点的副本,不留下任何指向已分配内存的内容。
您可以通过从函数返回指针来解决这些问题:
node_t *create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return ret;
}
然后将该指针保存在调用函数的tmp
中
tmp=create(i+100);
对于初学者来说,函数create应该返回指向动态创建的节点的指针。否则,您将无法释放已分配的节点,因为该函数返回已创建节点的副本。
所以至少像一样重写函数
node_t * create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return ret;
}
在main中的for循环中,您使用了一个未初始化的指针tmp。因此,在您定义的create函数实现中,由于带下划线的分配,循环调用未定义的行为
for(node_t*tmp;i++<10;head=tmp)
{
*tmp=create(i+100);
^^^^^^^^^^^^^^^^^^
tmp->next=head;
}
因此,在更改函数后,创建类似的更改循环
for(node_t*tmp;i++<10;head=tmp)
{
tmp=create(i+100);
tmp->next=head;
}
这是您更新的程序。
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
void *next;
} node_t;
void printlist(node_t*head){
for(node_t*i=head;i;i=i->next)
printf("%in",i->value);
}
node_t * create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return ret;
}
int main(){
int i=0;
node_t*head=0;
for(node_t*tmp;i++<10;head=tmp)
{
tmp=create(i+100);
tmp->next=head;
}
printlist(head);
}
其输出为
110
109
108
107
106
105
104
103
102
101