下面是向升序链表中添加新节点的程序。
下面的程序有bug,导致segmentation Fault
,我用gdb
找出了分割故障的原因。
但我没有得到什么是reason
分割故障。谁能告诉我分段故障的原因?
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data ;
struct node *link ;
} ;
void add ( struct node **, int ) ;
void display ( struct node * ) ;
int main( )
{
struct node *p ;
p = NULL ;
add ( &p, 5 ) ;
add ( &p, 1 ) ;
add ( &p, 6 ) ;
add ( &p, 4 ) ;
add ( &p, 7 ) ;
display ( p ) ;
}
void add ( struct node **q, int num )
{
struct node *r, *temp = *q ;
r = ( struct node *) malloc ( sizeof ( struct node ) ) ;
r -> data = num ;
if ( *q == NULL || ( *q ) -> data > num )
{
*q = r ;
( *q ) -> link = temp ;
}
else
{
while ( temp != NULL )
{
if ( temp -> data <= num && ( temp -> link -> data > num ||
temp -> link == NULL ))
{
r -> link = temp -> link ;
temp -> link = r ;
return ;
}
temp = temp -> link ;
}
}
}
void display ( struct node *q )
{
printf ( "n" ) ;
while ( q != NULL )
{
printf ( "%d ", q -> data ) ;
q = q -> link ;
}
}
我改变了这一行的顺序
if ( temp -> data <= num && ( temp -> link -> data > num || temp -> link == NULL ))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if ( temp -> data <= num && ( temp -> link == NULL || temp -> link -> data > num ))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
以上改变了工作,但我不知道这些变化背后的原因。
所以帮我找出原因
* *更新
如果短路计算是真正的原因,那么为什么下面的程序工作
int main()
{
int a=10,b=1,c=0;
int d;
d = (a && (c || b));
printf("%d",d);
getchar();
}
表达式
temp -> link -> data > num || temp -> link == NULL
将首先计算逻辑或的左侧,如果为假,则计算右侧。这意味着如果temp->link
是NULL
,那么你有未定义的行为当你解引用一个NULL
指针。
所做的更改是改变逻辑或表达式中两个子表达式的求值顺序,因此首先检查temp->link
不是NULL
,然后取消对temp->link
的引用。
当你这样做时-
if ( temp -> data <= num && ( temp -> link -> data > num || temp -> link == NULL ))
在temp -> link -> data
中,如果temp -> link
等于或当temp -> link
等于NULL
,则该表达式变为NULL -> data
。你正在尝试解引用NULL。所以你会得到segmentation fault
.
if ( temp -> data <= num && ( temp -> link == NULL || temp -> link -> data > num ))
在这种情况下,你不会得到分割错误。因为当temp -> link
是NULL
条件为真时,程序执行进入循环体。所以你不会得到segmentation fault
。但是当temp -> link
不是NULL
时,它将取消对它的引用。
在if语句的第二个版本中,短路求值将确保temp->link
永远不会被解引用。