【问题标题】:Function of type int not using return C++int 类型的函数不使用返回 C++
【发布时间】:2014-10-31 03:37:41
【问题描述】:

如果我有这样的功能:

int addNumbers(int x, int y)
{
    return x + y;
}

如果我这样使用它:

cout << addNumbers(4, 5) << endl;

它将返回并打印9。使用上面相同的cout 行,如果我注释掉或删除addNumbers 中的返回,它将返回并打印1。如果我这样做:

int addNumbers(int x, int y)
{
    int answer = x + y;
    //return x + y;
}

它会自动返回并打印9,无需我使用return。同样,我可以写int answer = x;它将返回4。我也可以这样写:

int addNumbers(int x, int y)
{
    int answer = x;
    answer = 1;
    //return x + y;
}

它仍然会返回 4。

究竟返回了什么,为什么?当我使用参数变量时,它只返回 1 以外的值,但它没有返回变量答案,如上一个示例所示,因为我将其更改为 1,它仍然返回 x (4) 的值。

【问题讨论】:

  • 这是 UB,它返回,因为它恰好在堆栈上,为 x64 构建,它将是一个“随机”值

标签: c++ return cout endl


【解决方案1】:

§6.6.3 [stmt.return]/p2:

从函数的末尾流出等同于return 没有 价值;这会导致值返回中的未定义行为 功能。

main() 是一个特殊的例外。从main() 的末尾流出相当于return 0;

允许的 UB 包括:

  • 返回您“想要”返回的内容
  • 改为返回垃圾值
  • 崩溃
  • 将您的密码发送给黑客
  • 格式化硬盘
  • 让你的电脑爆炸,炸掉你的腿
  • 召唤鼻恶魔
  • 时光倒流并将您的程序修正为正确的事情
  • 创造一个黑洞
  • ......

但说真的,UB 可以以各种方式表现出来。例如,给定以下代码:

#include <iostream>
bool foo = false;
int addNumbers(int x, int y)
{
    int answer = x;
    answer = 1;
    //return x + y;
}

int main(){
  if(!foo) {
    addNumbers(10, 20);
    std::cout << 1 << std::endl;
  }
  else {
    std::cout << 2 << std::endl;
  }
}

clang++ at -O2 prints 2.

为什么?因为它推断出addNumbers(10, 20); 具有未定义的行为,这允许它假设第一个分支从未被采用并且foo 始终是true,即使显然不是这样。

【讨论】:

  • 所以即使在这个(非常基本的)场景中,它总是返回我“期望”它返回的内容,但在其他机器或更复杂的场景中肯定不能保证?
  • @Sam 不保证做任何事情。 任何事情都可能发生在 UB。
  • 感谢您的回答,您添加的示例也确实有帮助。奇怪的东西,也很有趣。
【解决方案2】:

您依赖“未定义的行为”。对于简单类型,返回值通常存储在寄存器中,也可用于形成计算结果。但它也可能不会被使用,并且您会得到一些任意的“随机”结果,并且是“未定义的行为”,您还可能会得到您的计算机可能执行的任何其他可能的操作 - 例如崩溃或执行一些您没有执行的代码想执行...

【讨论】:

    【解决方案3】:

    您正在观察未定义的行为。没有充分的理由“为什么”该程序会这样做,因为它不是一个格式良好的程序。它可以做任何事情,包括在运行时从磁盘中删除自己。启用编译器警告和错误(例如g++ -Wall -Wextra -Werror),您将被自动阻止编写此类代码(您应该这样做)。

    【讨论】:

      【解决方案4】:

      因此这是未定义的行为,反汇编您的二进制文件可以解释为什么返回这些值。

      objdump -d example.bin

      由于返回值与rax注册表相关联,如果编译器使用rax处理函数,返回值就是保留在rax中的值。

      无论如何,您不应该这样做,因为当您编写此类代码时,编译器优化和注册表的使用是未知的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-18
        • 1970-01-01
        • 2015-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多