我们不必将函数的返回值赋给变量吗?C/C++

Mik*_*ike 6 c++ return function

我已经使用C/C++大约三年了,我不敢相信我以前从未遇到过这个问题!

以下代码编译(我刚刚尝试使用gcc):

#include <iostream>

int change_i(int i) {
  int j = 8;
  return j;
}

int main() {
  int i = 10;
  change_i(10);
  std::cout << "i = " << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

并且,程序打印i = 10,正如您所料.

我的问题是 - 为什么要编译?我本来期望一个错误,或者至少是一个警告,说有一个未使用的返回值.

天真地,我会认为这是一个类似的情况,当你不小心忘记非void函数中的返回调用.我明白这是不同的,我可以看到为什么这个代码没有任何内在错误,但它似乎很危险.我刚刚在我的一些非常古老的代码中发现了类似的错误,代表了一个可以追溯到很久的错误.我显然应该这样做:

i = change_i(10);
Run Code Online (Sandbox Code Playgroud)

但是忘了,所以它永远不会改变(我知道这个例子很愚蠢,确切的代码要复杂得多).任何想法将不胜感激!

Mar*_*ica 6

它编译是因为调用函数并忽略返回结果非常常见.事实上,主要的最后一行也是如此.

    std::cout << "i = " << i << std::endl;
Run Code Online (Sandbox Code Playgroud)

实际上是:

    (std::cout).operator<<("i =").operator<<(i).operator<<(std::endl);
Run Code Online (Sandbox Code Playgroud)

...而且你没有使用决赛中返回的值operator<<.

一些静态检查器可以选择在忽略函数返回时发出警告(然后选择注释通常忽略返回的函数).Gcc有一个选项可以将函数标记为要求使用返回值(__attribute__((warn_unused_result))) - 但它仅在返回类型没有析构函数时才有效:-(.


dbu*_*ush 2

忽略函数的返回值是完全有效的。以此为例:

printf("hello\n");
Run Code Online (Sandbox Code Playgroud)

我们忽略printf这里的返回值,它返回打印的字符数。在大多数情况下,您并不关心打印了多少个字符。如果编译器对此发出警告,那么每个人的代码都会显示大量警告。

这实际上是忽略表达式值的特定情况,在这种情况下,表达式的值是函数的返回值。

同样,如果您这样做:

i++;
Run Code Online (Sandbox Code Playgroud)

i您有一个表达式,其值被丢弃(即递增之前的值),但是++运算符仍然递增变量。

赋值也是一个表达式:

i = j = k;
Run Code Online (Sandbox Code Playgroud)

这里有两个赋值表达式。一个是,其值是(刚刚分配给)j = k的值。然后将该值用作右侧的另一个赋值给。然后表达式的值将被丢弃。kjii = (j = k)

这与非 void 函数不返回值有很大不同。在这种情况下,函数返回的值是未定义的,并且尝试使用该值会导致未定义的行为

忽略表达式的值并没有什么未定义的。