【问题标题】:why a function with returntype in c works with out return statement? [duplicate]为什么 c 中具有返回类型的函数在没有返回语句的情况下工作? [复制]
【发布时间】:2011-05-10 16:14:16
【问题描述】:

可能重复:
Why can you return from a non-void function without returning a value without producing a compiler error?

void main()
{
    int y=0;
    clrscr();
    printf("%d\n",Testing());
    y=Testing();
    printf("%d",y);
    getch();
}
int  Testing()
{
    int x=100;
    //return x;
}

Result 
512
4

我没有从测试函数返回任何东西仍然值来了吗?

还有一个问题

void main()
{
    char Testing();
    int y=0;
    clrscr();
    printf("%d\n",Testing());
    if(Testing())
        printf("if--exi");
    else
        printf("else--exi");
    getch();
}
char Testing()
{
    char y;
    //return y;
}

Result

0
if--exi

如果 printf 被注释,那么结果是

else--exi

为什么会这样

【问题讨论】:

  • 我认为没有返回的函数将是未定义的行为,并且至少会触发一个警告......
  • 有警告但它仍在工作 内部发生了什么?
  • 为什么同时标记C和C++?这些语言在这方面有很大的不同。
  • Er... 通过删除 [C++] 标记,您基本上使 Mark B 的答案无效,您自己将其标记为已接受。结论是正确的,但该答案中给出的解释是特定于 C++ 的,即在 C 语言的上下文中,该解释在技术上是不正确的。

标签: c


【解决方案1】:

声明为返回值的函数在没有返回的情况下到达路径具有未定义的行为。您只是很不幸,它似乎仍在返回一个半合理的值。编译器假定在函数的所有退出中调用return,并且返回值将在特定位置可用。

在您的第二个示例中,任何事情都可能发生,包括每次调用返回不同的值。

g++ 有检测此问题的警告,非常值得启用。

【讨论】:

  • “似乎可以工作”?你怎么能这样说? :P 你预测/期望什么输出?在什么基础上?
  • @Nawaz:而不是直接崩溃。
  • 从 C++ 语言的角度来看,您的答案是正确的,但在 C 语言中则不然。在 C 语言中,仅到达值返回函数的末尾不会导致未定义的行为。在 C 中,未定义的行为仅在您尝试在调用者中使用“返回”值时发生。当然,OP 的代码在两种语言中仍然存在问题,但原因不同。从问题的标题来看,OP 暗示的是 C,而不是 C++。
  • @Nawaz 我改变了措辞,希望更清楚。我的意思是“某事”发生了,而不是编译失败或崩溃。
【解决方案2】:

为什么您的问题同时标记为 C 和 C++,而标题却专门针对 C?这两种语言在这方面有很大的不同。

在 C 语言中,这样的函数“工作”是因为语言要求它们工作。为什么不?用某种返回类型声明的函数可能仍然做一些有用的工作(除了返回任何东西)。因此,从正式的角度来看,在这样的函数中没有 return 语句是完全可以的。虽然这不是一个好的编程习惯。只要您不尝试使用返回的值(该函数并未真正返回该值),该函数就会起作用。您正在尝试使用该值,这会使您的代码的行为未定义。您声称它“有效”。实际上它没有。在这种情况下会发生什么以及为什么 - 这些问题没有答案。无论如何,您的代码行为本质上是随机且不可预测的。

在 C++ 语言中,使用 return 语句“忘记”返回值的函数总是立即导致未定义的行为,无论调用者是否使用该值。

【讨论】:

  • “在这种情况下会发生什么以及为什么 - 这些问题没有答案。无论如何,您的代码行为本质上是随机且不可预测的。” - 真的?我想说的是返回值似乎是 EAX 寄存器中剩下的任何东西,这一点也不神秘。
  • @Heath Hunnicutt:这可能适用于一个非常具体的代码构建,由一个非常具体的编译器构建,具有一组非常具体的编译器选项和一组非常具体的启发式决策。编译器在非常特定的硬件平台上的内部算法。同时,我将这个问题视为关于 C 语言的通用问题,因为它被标记为 [C]。
  • @Heath Hunnicutt:有人可能会争辩说,我们生活中没有什么是真正随机和不可预测的,一切都可以通过从大爆炸那一刻起追踪特定原子(或其他一些粒子)的路径来预测.在某种程度上(作为一个“荒谬的”类比)这非常接近您所倡导的 EAX 理论。另一方面,我不认为这是一种特别有效的方法。
  • 一个人可能会做出一个“荒谬的”类比,但这样就会与自己的稻草人争论。事实上,了解您平台的 C ABI 是使用 C 的一部分。可能有些人不这么认为,但他们可能不适用于 C 中的设备驱动程序。
【解决方案3】:

它只是您返回的内存中的随机垃圾,因此,第二个示例中的每个调用都会产生不同的结果

【讨论】:

    【解决方案4】:

    获取声明为不返回任何内容的函数的返回值是未定义的行为。

    未定义的行为意味着任何事情都是可能的,并且操作的结果不是由 C++ 标准定义的。您无法估计或近似任何程序运行的结果。

    【讨论】:

      【解决方案5】:

      您正在导致未定义的行为,因此 任何 输出都是可能的。

      【讨论】:

        【解决方案6】:

        从技术上讲,您正在调用“未定义的行为”。未定义的行为表现得很好,没有定义。如果您的程序的行为未定义,它可能会打印 512、4、99,甚至是葛底斯堡地址的完整文本。

        我不会将您显示的结果描述为任何合理意义上的“工作”。

        附:如果您使用的是 GNU Compiler Collection,我建议至少使用这些开关:“-Wall -Werror”。

        P.p.s.在过去的几年里,在 ANSI 标准 C 之前的日子里,某个非优化的 Z-80 C 编译器会接受这个程序片段:

        int ReturnThree() {
          3;
        }
        

        并生成与用户指定的代码相同的代码:

        int ReturnThree() {
          return 3;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-12
          • 2013-05-29
          • 2016-12-31
          • 2020-06-20
          • 1970-01-01
          • 2017-06-20
          • 1970-01-01
          • 2019-09-07
          相关资源
          最近更新 更多