与 Java 不同,在 C/C++ 中允许以下内容:
int* foo ()
{
if(x)
return p;
// what if control reaches here
}
这通常会导致崩溃和难以调试的问题。为什么标准不强制对非函数进行最终返回?(编译器会为错误的值void
生成错误)return
gcc/msvc 中是否有任何标志来强制执行此操作?(类似-Wunused-result
)
与 Java 不同,在 C/C++ 中允许以下内容:
int* foo ()
{
if(x)
return p;
// what if control reaches here
}
这通常会导致崩溃和难以调试的问题。为什么标准不强制对非函数进行最终返回?(编译器会为错误的值void
生成错误)return
gcc/msvc 中是否有任何标志来强制执行此操作?(类似-Wunused-result
)
这是不允许的(未定义的行为)。但是,在这种情况下,该标准不需要诊断。
该标准不要求最后一条语句是return
因为这样的代码:
while (true) {
if (condition) return 0;
}
这总是返回 0,但愚蠢的编译器看不到它。请注意,该标准不强制要求智能编译器。块之后的return
语句while
将是一种浪费,愚蠢的编译器将无法优化。该标准不想要求程序员编写废代码只是为了满足愚蠢的编译器。
g++ -Wall 足够聪明,可以在我的机器上发出诊断信息。
-Wall
在gcc
. _
warning: control reaches end of non-void function
编辑:或更具体地说-Wreturn-type
。
我的猜测:因为有时程序员比编译器更了解。通过这个简单的示例,很明显有些地方是错误的,但考虑一个切换多个值或多个检查的一般情况。作为编码人员,您知道某些值不会传递给函数,但编译器不会,只是提示您,可能有问题。
#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
请注意,即使 MSVC 上的警告级别 1 也会发出以下警告:
警告 C4715:“foo”:并非所有控制路径都返回值
AFAIR Visual Studio 2008 警告您“没有返回值的执行路径”。意思是“C++ 不会阻止你朝你的脚开枪”是允许的。所以你要思考,而不是编译器。
显而易见的答案是:因为这不是错误。如果为 false 并且调用者使用返回值,这只是一个错误
x
,编译器不一定能确定这两者,至少在一般情况下。
return
在这种特殊情况下(返回一个指针),对所有路径都要求 a 并不难;Java 就是这样做的。然而,一般来说,在 C++ 中要求这个是不合理的,因为在 C++ 中,您可以返回可能无法构造值的用户定义类型(没有默认构造函数等)所以我们遇到程序员的情况可能无法return
在他或她知道不能采用的分支中提供 a,并且编译器无法确定该分支不能采用。
大多数编译器会在这种情况下发出警告,当它可以确定流程时。然而,在某些情况下,我所看到的所有这些也都发出警告,显然不可能从末端掉下来。(g++ 和 VC++ 都警告:
int
bar( char ch )
{
switch ( ch & 0xC0 ) {
case 0x00:
case 0x40:
return 0;
case 0x80:
return -1;
case 0xC0:
return 1;
}
}
,至少使用通常的选项。虽然很明显,这个功能永远不会落到最后。)
标准对这种编程的说法是它会产生未定义的行为。
未定义的行为是 C/C++ 的乐趣和遗憾,但它也是语言设计的一个基本特征,允许许多低级优化使 C 成为一种“高级汇编程序”(实际上不是,但只是给你一个想法)。
因此,在重定向到约翰关于使用 GCC 的开关的回答时,要知道“为什么”标准不会阻止这一点,我会指出对未定义行为及其所有谜团的非常有趣的分析:每个 C 程序员应该知道的关于未定义的行为。它是一个非常有启发性的阅读。