如果您不熟悉动态内存分配,则可以将其视为大脑绞痛。
首先将此代码另存为bin程序中的C程序。
#include<stdio.h>
#include<conio.h>
struct node {
int data;
struct node *next;
} *head=NULL;
void ins_at_beg()
{
struct node *node=malloc(4);
node->next=head; head=node;
printf("Please enter the value to be inserted at the start: ");
scanf("%d",node); // POINT A
}
void ins_at_end()
{
struct node *node=head;
while(node->next) node=node->next;
node->next=malloc(4);
printf("Please enter the value to be inserted at the end: ");
scanf("%d",node->next->data); // POINT B
}
void main()
{
clrscr();
ins_at_end();
printf("%d",head->data);
getch();
}
执行此代码,一切都会正常。
现在,在程序将主要功能的ins_at_end()
执行到ins_at_beg()
并执行了程序之后,一切仍然看起来很好。
现在手动撤消上述更改(将ins_at_beg
更改为ins_at_end
)并执行程序。现在,您将获得head->data
的值为0。
现在,只需将“ Point A”的node
更改为node->data
,您将看到输入的值会反映在屏幕上(注意:我们没有在主要功能)
现在再次反转上述更改,并将0作为默认值head->data
。
这里要注意的主要事情是,输出会被刚刚定义的函数更改,而该函数在主函数中未调用。
玩一会儿,您就会知道我在说什么。
问题:,即使我实际上没有调用在主函数中进行更改的函数,将node
更改为node->data
时,程序为何仍能正常工作功能?
答案 0 :(得分:2)
此:
scanf("%d",node);
这:
scanf("%d",node->next->data);
不正确。 %d
格式说明符期望int *
作为参数。但是,在一种情况下,您传递的是struct node *
,在另一种情况下,您传递的是int
。对scanf
使用错误的格式说明符会调用undefined behavior,这就是为什么您看到奇怪结果的原因。
您应该这样做:
scanf("%d",&node->data);
这:
scanf("%d",&node->next->data);
此外,这还假设了指针的大小:
struct node *node=malloc(4);
您应该这样做:
struct node *node=malloc(sizeof(*node));
您在这里也遇到了问题:
void ins_at_end()
{
struct node *node=head;
while(node->next) node=node->next; // <--- here
node->next=malloc(4);
printf("Please enter the value to be inserted at the end: ");
scanf("%d",node->next->data); // POINT B
}
在程序启动时,head
为NULL,因此您试图取消引用NULL指针,这再次导致未定义的行为。在执行其他任何操作之前,请检查这种情况。另外,您应将列表末尾的next
指针显式设置为NULL。
void ins_at_end()
{
struct node *node=malloc(sizeof(*node));
struct node *tmp;
printf("Please enter the value to be inserted at the end: ");
scanf("%d",&node->data);
node->next = NULL;
if (!head) {
head = node;
} else {
tmp = head;
while (tmp->next) tmp = tmp->next;
tmp->next = node;
}
}