没有返回语句的 C 和 C++ 函数

2022-01-19 00:00:00 return c c++

在查看工作中的代码时,我发现了一些(看似)令人反感的代码,其中函数具有返回类型,但没有返回.我知道代码可以工作,但认为这只是编译器中的一个错误.

While looking through code at work I found some (seemingly) offensive code in which a function had a return type, but no return. I knew the code worked, but assumed it was just a bug in the compiler.

我编写了以下测试并使用我的编译器运行它(gcc (Homebrew gcc 5.2.0) 5.2.0)

I wrote the following test and ran it using my compiler (gcc (Homebrew gcc 5.2.0) 5.2.0)

#include <stdio.h>

int f(int a, int b) {
  int c = a + b;
}

int main() {
   int x = 5, y = 6;

   printf("f(%d,%d) is %d
", x, y, f(x,y)); // f(5,6) is 11

   return 0;
}

类似于我在工作中找到的代码,默认返回函数中执行的最后一个表达式的结果.

Analogous to the code I found at work, this defaults to returning the result of the last expression executed in the function.

我发现 这个 问题,但对答案不满意.我知道使用 -Wall -Werror 可以避免这种行为,但为什么它是一个选项?为什么这仍然允许?

I found this question, but was not satisfied with the answer. I know that with -Wall -Werror this behavior can be avoided, but why is it an option? Why is this still allowed?

推荐答案

为什么仍然允许这样做?"不是,但一般来说,编译器无法证明您正在这样做.考虑这个(当然是极其简化的)示例:

"Why is this still allowed?" It is not, but in general, the compiler cannot prove you are doing it. Consider this (of course extremely simplified) example:

// Input is always true because logic reason
int fun (bool b) {
    if (b) {
        return 7;
    }
}

甚至是这个:

int fun (bool b) {
    if (b) {
        return 7;
    }
    // Defined in a different translation unit, will always call exit()
    foo();
    // Now we can never get here, but the compiler cannot know
}

现在第一个示例可以结束,但只要正确"使用该函数,它就永远不会;第二个不能,但编译器不知道这一点.因此,编译器会通过使其成为错误来破坏工作"和合法的代码,尽管可能很愚蠢.

Now the first example could flow off the end, but it never will as long as the function is used "properly"; and the second one could not, but the compiler cannot know this. So the compiler would break "working" and legal, although probably stupid, code by making this an error.

现在您发布的示例有点不同:这里,所有 路径从末尾流出,因此编译器可以拒绝或忽略此函数.然而,它会破坏现实世界中依赖于编译器特定行为的代码,就像在您的生产代码中一样,人们不喜欢这样,即使他们错了.

Now the example you posted is a little different: Here, all paths flow off the end, so the compiler could reject or just ignore this function. It would however break real world code that relies on the compiler specific behavior as in your production code, and people do not like that, even if they are wrong.

但最终,从非 void 函数的末尾流出仍然是未定义的行为.它可能适用于某些编译器,但不能保证也不能保证.

But in the end, flowing off the end of a non-void function still is undefined behavior. It might work on certain compilers, but it is not and never was guaranteed to.

相关文章