【问题标题】:Please explain the output of the following code [duplicate]请解释以下代码的输出[重复]
【发布时间】:2015-07-17 14:27:01
【问题描述】:

有人可以解释以下代码的行为吗?返回类型为 int 的函数 message() 怎么会返回 printf() 函数打印的字符数而没有任何返回语句?

#include <stdio.h>

int message();

int main() {
  int c;
  printf("C before:%d\n",c);
  c=message();
  printf("C after:%d\n",c);
  return 0;  
}

int message(){
  printf("From the message");
}

【问题讨论】:

  • 未定义行为的(反)奇迹。
  • printf 返回字符数。它的返回值显然放在堆栈的某个地方。在某些实现中,将函数调用分配给变量的实现显然是某种指针,指向如果函数返回值,函数将返回值的位置。由于没有返回值,因此您正在执行类似悬空指针的操作。在这个实现中,它碰巧指向一个与函数所做的事情相关的值,但 C 标准中没有任何东西可以保证这种行为。

标签: c printf


【解决方案1】:

这是由未定义的行为引起的。
这是similar question,我不能说它比second answer 做得更好:

这只是未定义的行为;如果您不填充返回区域 [...],它将通过您的函数中的某些副作用获得最后设置的值。

...这是printf返回的值。

【讨论】:

    【解决方案2】:

    这是未定义的行为 ...

    由于message()中没有设置return,所以会将C设置为垃圾。

    【讨论】:

    • 标准没有规定c 的单一值,但在这种情况下,它不是“垃圾”;这是printf 的缓存返回值。当然,由于是 UB,它可能在另一个编译器/系统上完全不同,所以它也可能是垃圾。
    • 我会把它归类为垃圾。 - 啊 - 你编辑了你的评论! :-)
    • 我的意思是,在这种情况下,在那个系统上,它不是一个随机值。但是,是的,可以肯定的是,UB 是垃圾,因为没有人应该故意对其进行编程。 - 啊,你看到了我的编辑。 :D
    • 在某些方面它比垃圾还糟糕。这是一个可预测的值(至少在 gcc 中),但不能保证。如果您针对特定的编译器,您可以编写使用这些伪返回的功能代码。但是随后另一个编译器(或者甚至可能具有不同设置的相同编译器)可能会破坏代码。就像食用垃圾一样,会毫无征兆地变成有毒物质。
    【解决方案3】:

    这是未定义的行为。

    例如,如果你用 clang 编译并运行它,结果是不同的。 gcc -O0 产生字符串长度,-O2 和 -O3 产生 0。

    也许 printf 的返回值和 message 一样被放入同一个寄存器中。并且消息在返回之前不会重置寄存器。

    【讨论】:

    • 感谢罗尼的回答 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    相关资源
    最近更新 更多