#include <stdio.h>
typedef struct node
{
int i;
struct node *next;
}node;
node getnode(int a)
{
struct node n;
n.i=a;
n.next=NULL;
return n;
}
main()
{
int i;
node newtemp,root,temp;
scanf("%d",&i);
root=getnode(i);
temp=root;
while(i--)
{
newtemp=getnode(i);
temp.next=&newtemp;
if(root.next==NULL)
{
root=temp;
}
temp=*(temp.next);
}
temp=root;
while( temp.next != NULL )
{
printf(" %d ",temp.i);
temp=*(temp.next);
}
}
我正在尝试在不使用malloc的情况下创建链接列表。编程只打印根,后面没有节点。我找不到这个bug。如果有任何内存问题,gcc编译器会抛出一个分段错误。(?)请忽略糟糕的编程风格..
答案 0 :(得分:17)
初始化temp.next
时,指定给它的指针的值是多少?
temp.next=&newtemp;
为什么,每次都是一样的! (如果你不相信,请画一幅画。)
放弃。如果你需要一个不确定数量的内存(你有不确定数量的节点),那么你需要分配内存。
答案 1 :(得分:11)
你可以避免使用malloc但不是免费的:
答案 2 :(得分:6)
您只有两个可用于存储节点的内存空间,它们是root
和newtemp
。将新节点分配给newtemp
时,旧节点不再存在。
假设您在第一次迭代循环之前在scanf处输入了数字5
,您有:
5 -> NULL
在循环的第一次迭代之后,你有
5 -> 4 -> NULL
在循环的第二次迭代之后,你有
5 -> 3 -> NULL
(包含4
的节点已被包含3
的节点完全取代。
唯一的解决方案是使用malloc
,并使getnode
返回node*
。
答案 3 :(得分:5)
您可以静态声明节点结构数组并从该数组中选择新节点。但是,你会实现一个蹩脚,可悲的专业自定义分配器。并且可用节点的最大数量将是该阵列的大小。
或者,您可以使用递归作为分配机制,并对递归堆栈底部的列表执行操作。
这两种方法大致相同。
答案 4 :(得分:4)
当然,您可以构建链接列表或任何其他数据结构,而无需动态内存分配。 但是,无论你怎么努力,你都不能构建它,根本不分配内存。
替代:
创建一个全局或静态内存池,您可以在其中放置对象,模仿heap / malloc / free。 FreeRTOS做的事情就像。 在这种情况下,你将有一个静态分配的大内存块,因为你的程序开始和将负责管理它,当需要一个新节点时返回正确的指针并将该内存标记为已使用
P.S。:我不会质疑你为什么要避免使用malloc。我认为你有充分的理由。
在你的程序中,当你这样做时,在第20行:
node newtemp,root,temp;
你是allocatin thre节点,其中之一是“newtemp”。 然后你在第28行:
newtemp=getnode(i);
它只是复制返回节点的内容而不是旧的“newnode”(争议,不是吗?)
所以你这样做,吼叫:
temp.next=&newtemp;
将最初来自“root.next”的指针设置为“newnode”。
if(root.next==NULL)
首次通过时会为“NULL”,但只会替换相同的内容。
temp=*(temp.next);
{
root=temp;
}
再次将数据从单个已分配对象“*(temp.next)”复制到另一个“temp”。 它不会创建任何新节点。
如果您这样做,它将起作用:
#include <stdio.h>
typedef struct node
{
int i;
struct node *next;
}
node;
#define MAX_NODES 10
node *create_node( int a )
{
// Memory space to put your nodes. Note that is is just a MAX_NODES * sizeof( node ) memory array.
static node node_pool[ MAX_NODES ];
static int next_node = 0;
printf( "[node *create_node( int a )]\r\tnext_node = %d; i = %d\n", next_node, a );
if ( next_node >= MAX_NODES )
{
printf( "Out of memory!\n" );
return ( node * )NULL;
}
node *n = &( node_pool[ next_node++ ] );
n->i = a;
n->next = NULL;
return n;
}
int main( )
{
int i;
node *newtemp, *root, *temp;
root = create_node( 0 );
temp = root;
for ( i = 1; ( newtemp = create_node( i ) ) && i < MAX_NODES; ++i )
{
temp->next = newtemp;
if ( newtemp )
{
printf( "temp->i = %d\n", temp->i );
printf( "temp->next->i = %d\n", temp->next->i );
temp = temp->next;
}
}
for ( temp = root; temp != NULL; temp = temp->next )
printf( " %d ", temp->i );
return 0;
}
输出:
$ gcc -Wall -o list_no_malloc list_no_malloc.c
$ ./list_no_malloc
[node next_node = 0; i = 0)]
[node next_node = 1; i = 1)]
temp->i = 0
temp->next->i = 1
[node next_node = 2; i = 2)]
temp->i = 1
temp->next->i = 2
[node next_node = 3; i = 3)]
temp->i = 2
temp->next->i = 3
[node next_node = 4; i = 4)]
temp->i = 3
temp->next->i = 4
[node next_node = 5; i = 5)]
temp->i = 4
temp->next->i = 5
[node next_node = 6; i = 6)]
temp->i = 5
temp->next->i = 6
[node next_node = 7; i = 7)]
temp->i = 6
temp->next->i = 7
[node next_node = 8; i = 8)]
temp->i = 7
temp->next->i = 8
[node next_node = 9; i = 9)]
temp->i = 8
temp->next->i = 9
[node next_node = 10; i = 10
Out of memory!
0 1 2 3 4 5 6 7 8 9
答案 5 :(得分:2)
链接列表的长度不确定,如果没有malloc,则无法创建任何长度不确定的列表。
我建议你只使用malloc来分配链中的下一个链接。
答案 6 :(得分:1)
当使用malloc时,该位置的“指针”将传递给变量(这是一个指针)。
node* new = (node*)malloc(sizeof(node));
每次使用此代码时,都会指向“新”位置。相反,您使用的是常规变量,它们具有“静态”分配的内存。这意味着,每当你提到'temp'或'newtemp'时,你指的是每个时间相同的位置。
现在你告诉我如何使用3个(root,temp,newtemp)内存位置存储10个元素的长列表。您可能想要绘制内存位置以想象发生了什么。但请记住,每次将'temp'称为SAME内存位置。为此,我们必须使用malloc(或calloc)来动态分配内存。
在这种情况下,我们可以使用少量指针(远远小于列表使用的内存)。
答案 7 :(得分:0)
由于现代C(又名C99)的精神中没有人回答过关于malloc
部分的这个问题。如果您的编译器符合您的可变长度数组:
node myNodes[n];
其中n
具有仅在运行时确定的某个值。您可能不应该使用此方法来覆盖它,因为这仅限于堆栈的大小,否则您可能会遇到堆栈溢出。