1

我有这个 C 代码,我确信它不会工作,但它确实有效。

#include <stdio.h>

int* find (int* a, int val) {
    if (*a == val)
        return a;
    else
        find(a+1, val);
}

int main() {
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *b;

    b = find(a, 7);

    printf("%d\n", *b);

    return 0;
}

当然,我收到了来自 gcc 的警告,因为它在find函数的 else 分支中缺少 return 语句。但是,它完美地工作。

为什么会这样?它怎么知道通过递归函数返回一个int?当然,最后一次调用返回一个 int,但我在 void 上下文中调用它。

4

4 回答 4

7

此代码不是有效的 C 代码,并且未定义此类代码的行为。

它起作用的一个原因可能是在最后一次调用之后没有任何操作,find可能导致递归调用的返回值保留在返回寄存器中(可能是 eax)。

但同样 - 行为是未定义的

于 2013-02-07T14:31:58.357 回答
3

似乎有效,但它是未定义的行为。只是碰巧在您的特定实现/平台b中采用从find. 但是,在不同的实现/平台上,这也可能会崩溃。

于 2013-02-07T14:31:15.230 回答
2

假设您打算写作find而不是trova(我知道学习意大利语有一天会派上用场:),答案是这并不完美。由于未定义的行为,它纯粹是偶然地“起作用”。

最有可能的是,最深的递归调用将返回值推送到某个寄存器中,更高级别的调用不会触及这些寄存器,因为它们没有 return 语句,并且当调用者检查该寄存器时,最深调用的返回值还在那里。不过,你不能依赖这个。

于 2013-02-07T14:30:50.083 回答
-1

我找不到参考,但我记得几年前,在 GCC 中,返回值寄存器(在 CPU 上分配)总是有最后一个返回值,所以如果你计算了一些值并且没有返回值,前一个价值持续存在。使用此“功能”似乎是一种不好的做法。

也许还看到

http://stackoverflow.com/questions/1610030/why-can-you-return-from-a-non-void-function-without-returning-a-value-without-pr

C:如果没有给出值,默认返回值?

那说: Uniballer 2012 年 6 月 15 日,01:44 C 语言未定义行为,因为您没有在函数中执行您在函数声明中所说的操作。实际上,在 x86 上,函数的值将是返回时寄存器 eax 中发生的任何值。

于 2013-02-07T15:13:09.653 回答