C 中的递归函数有返回值但没有返回值

Byz*_*thr 3 c recursion return binary-search-tree

所以我正在用 C 编写一些二叉搜索树函数(这里是完美工作的节点结构和插入函数):

typedef struct searchTreeNode {
    int data;
    struct searchTreeNode *left;
    struct searchTreeNode *right;
} STNode;


void insert(STNode **proot, int data) {

    STNode *node = *proot;
    if (!node) {
        *proot = newNode(data);
        return ;
    }
    if (data <= node -> data) insert(&(node -> left), data);
    else insert(&(node -> right), data);
}
Run Code Online (Sandbox Code Playgroud)

我发现以下用于查找树的最大值的递归函数工作得很好,即使最后一个递归调用实际上返回一个整数:

int max(STNode *node) {

    if (!node) return 0;
    if (!(node -> right)) return node -> data;
    max(node -> right);
}
Run Code Online (Sandbox Code Playgroud)

这意味着,如果我没记错的话,它的作用与此完全相同:

int max(STNode *node) {

    if (!node) return 0;
    if (!(node -> right)) return node -> data;
    return max(node -> right);
}
Run Code Online (Sandbox Code Playgroud)

函数现在返回从下一个递归调用获得的值。

这是函数返回最后一个返回值的已知行为还是我遗漏了什么?

这是我的主要函数,其中包含一些随机数:

int main() {

    STNode *root = NULL;
    insert(&root, 10);
    insert(&root, 13);
    insert(&root, 14);
    insert(&root, 124);
    insert(&root, 1);
    insert(&root, 8);
    insert(&root, 3);

    printf("Max value: %d\n", max(root));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Wer*_*nze 5

由于您的第一个版本max不是return所有路径上的值,因此当调用者尝试读取该值时,它会导致未定义的行为。编译器要做什么取决于编译器。不能保证编译器return在某处插入 a 。在这种情况下你不能依赖任何东西。

在您的特定平台上事实上可能发生的是路径

if (!node) return 0;
if (!(node -> right)) return node -> data;
Run Code Online (Sandbox Code Playgroud)

写入返回值的寄存器。递归调用max(node -> right);意味着最后return会发生上面两个中的一个,并且返回值将位于右侧寄存器中。因此,当max没有显式地静默返回时return ...;,编译器可能只会发出返回机器代码并保持返回寄存器不变。当然,这种情况只会发生,因为递归调用max是函数中的最后一个语句(修改返回寄存器)。

但正如所说,请不要这样做,这是未定义的行为,很可能会在将来给您带来麻烦。