他们将树中的节点定义为这样的结构:
struct Data{
char name[15];
int age;
Data *left,*right;
};
他们给了我们一个代码,可以在BST中搜索:
// temp is current node, name is the value of the node to be searched for.
Data* search(Data *temp,char name[]) {
if(strcmp(temp->name,name)>0)
search(temp->left,name);
else if(strcmp(temp->name,name)<0)
search(temp->right,name);
else
return temp;
}
我注意到代码错了。 如果函数进入第一个或第二个if块,它将不会执行任何return语句。
但是当实验室助理运行代码时,它的工作正常。
我认为这种行为可能是特定于编译器的。 但是当我在gcc上尝试该代码时,该函数也可以正常工作。 (我们的大学使用microsoft visual c ++编译器)
任何人都可以解释发生了什么吗?为什么这段代码有效?
PS:忽略其他错误,例如节点为空时,找不到值等等
答案 0 :(得分:8)
这只是未定义的行为。
出现,因为有一个寄存器保存了返回值。在递归树的最深路径中,temp
被移入该寄存器,之后从未清除或更改,因此寄存器将包含正确的节点,直到第一次调用返回。
当第一个调用返回时,调用上下文检查该寄存器的返回值,这恰好是正确的。但你不应该依赖于此。 不安全假设它始终有效。
答案 1 :(得分:1)
通常,您有一个硬件寄存器用于从函数返回值(例如,在i686上为%EAX)。如果你在函数中做的最后一件事是调用另一个函数并且预期的返回值是该函数的结果,那么可能会发生%EAX值没有被删除并被调用者很好地检索。
然而,这受到许多假设的影响,你不应该期望它在任何方面都是可靠的。首先,编译器可以检测到您没有使用search()
的返回值,因此如果它有关于search()
没有副作用的提示,它可能会决定优化该调用。如果它能够内联搜索调用,它可以部分地优化它。
可能存在其他体系结构(iirc,IA64就是这种情况),其中调用约定更加微妙,并且用于在一个函数中返回值的寄存器与调用函数中的寄存器不同。因此,您的代码依赖于依赖于平台的细节,而它应该是一种高级(和可移植)语言。