【问题标题】:How do C++ progs get their return value, when a return is not specified in the function?当函数中没有指定返回值时,C++ progs 如何获得它们的返回值?
【发布时间】:2011-03-28 10:50:39
【问题描述】:

我最近写了一个帖子:
Weird Error in C++ Program: Removing Printout Breaks Program

...我试图解决一个看似令人费解的问题,其中删除 cout 语句会破坏我的程序。

事实证明,我的问题是我忘记返回我后来用于逻辑的真/假成功标志。

但显然有些东西被退回了,如果我把那个 cout 留在里面,那东西总是正确的,但当我把它拿出来时,似乎“神奇地”变成了假。

我的问题是:
当函数内没有执行返回命令时,什么决定了 c++ 函数返回什么?有什么逻辑吗?

显然忘记返回类型是个坏主意。不过,在这种情况下,这主要是由于我的程序的性质——一个快速的 hack 工作。后来我决定不值得努力实现一个算法来确定函数调用的成功/失败——但不小心留下了依赖于返回的代码。

编译可执行文件时,g++ 没有给我任何警告或错误,如下所示:

g++ main.cc -g -o it_util

我的版本是: g++ (GCC) 4.1.2 20080704(红帽 4.1.2-44)

再次,为了避免其他人在犯同样愚蠢的错误并遇到同样看似不稳定的行为时感到沮丧,谁能阐明没有返回的函数从哪里获得返回值??

谢谢!!

【问题讨论】:

  • 如果使用-Wall 标志编译会发生什么?
  • 我猜eax上发生了什么?
  • 返回值是特定于机器/架构的。如果您举报您使用的操作系统/计算机/编译器组合(32 位/64 位)以及预期返回值的类型(int、结构、指针、浮点),那么有人可能会在这里帮助您。问候 rbo
  • 好点,尼尔。当我打开 -Wall 标志时,我收到警告 main.cc:278: warning: control reaches end of non-void function,所以我猜 g++ 确实 会警告我,但默认情况下只是关闭该警告。我想我应该记得下次使用那个标志,嗯?
  • @Jason 你应该设置你的环境,以便每次都使用 -Wall - 可能也添加 -Wextra 和 -pedantic。这些将为您节省大量时间。

标签: c++ memory return-value return


【解决方案1】:

在 x86 调用约定中,整数和指针的返回值在 EAX 寄存器上。下面是一个例子:

int func() {
    if(0) return 5; // otherwise error C4716: 'func' : must return a value
}
int main() {
    int a;
    a = func();
}

cl.exe /Zi编译,MSVC++10:

push    ebp
mov     ebp, esp
push    ecx
call    j_?func@@YAHXZ  ; func(void)
mov     [ebp+a], eax ; assumes eax contains the return value
xor     eax, eax
mov     esp, ebp
pop     ebp
retn

当然,这都是未定义的行为。

【讨论】:

    【解决方案2】:

    它没有逻辑,大多数 C++ 编译器都应该用警告标记它。它允许向后兼容 C。

    在 K&R C 中,没有 void 类型,当未指定类型时,默认为 int。所以,

    myfunc() {....}
    

    从技术上讲,它是一个返回 int 的函数,但大多数程序员将这种形式用于不返回值的例程。

    编译器必须理解这一点。因此,约定变成了,return 会将某些内容放入寄存器中。调用例程中的赋值将从寄存器中取出值。现在,如果被调用者从未发出返回,则不会在该寄存器中放置任何特定。但它仍然会有一些(随机)值,它会在调用者中盲目分配。

    【讨论】:

      【解决方案3】:

      来自 C++ 标准部分6.6.3 返回语句

      从函数的末尾流出的是 相当于没有价值的回报; 这会导致未定义的行为 一个值返回函数。

      有一个例外(根据 3.6.1/5):

      如果控制到达 main 的末尾而没有遇到返回 声明,效果是 执行返回0;

      James Curran 很好地说明了在语法上允许这样做的原因。但是使用 -Wall gcc 选项(正如 Neil 评论的那样)你应该被警告这种行为;类似“并非所有控制路径都在值返回函数中返回值...”。

      【讨论】:

      • 在现代 c++ 中是否存在这种行为?为什么默认没有警告(即为什么你必须在g++中打开-Wall才能看到错误?)?
      • @Jason:假设你有一个模板函数template<class T> T func() { return ; } template<> int func() { return 1; } template<class T> T func1() { return func<T>(); } int main() { func<void>(); func<int>(); return 0; } 现在编译器不能仅仅基于return 关键字来抱怨,不是吗?
      • @Jason: g++ 默认不给出警告。就是这样。
      • 有一个例外(3.6.1/5):如果控制到达main的末尾而没有遇到return语句,则效果是执行return 0;
      【解决方案4】:

      这取决于调用约定。例如,对于 Intel 平台上的 32 位整数返回,您将获得 eax 寄存器中的任何内容。

      【讨论】:

        【解决方案5】:

        使用现代编译器,您可能会使用 -Wall 收到警告

        但是如果你不返回一个值,通常你会得到垃圾。

        【讨论】:

          【解决方案6】:

          “什么决定了一个c++函数在函数内没有执行返回命令时返回什么?有什么逻辑吗?”

          函数开头的类型。

          例子:

          int 牛() { 国际温度; 返回温度; }

          如果你没有返回正确的类型或什么都不返回,编译器应该会抱怨。 编辑:哦,废话,我刚刚看了你的标志。你需要打开更多的标志,-W -Wall -pedantic。阅读 g++ 手册。

          除非你有一个 void 函数。然后你不必返回任何东西,或者你可以有指针来玩。

          void somefunction(int* ptr_int) { int temp = *ptr_int; 温度+=1000; this->ptr_int = temp; }

          我相信上面的代码可以工作,我已经有一段时间没有用 C++ 编写代码了。

          【讨论】:

            猜你喜欢
            • 2021-12-28
            • 2017-06-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-19
            • 2012-08-04
            • 1970-01-01
            • 2020-07-28
            相关资源
            最近更新 更多