17

Javaとは異なり、C /C++では次のことが許可されています。

int* foo ()
{
  if(x)
    return p;
// what if control reaches here
}

これにより、クラッシュが発生し、デバッグが困難になることがよくあります。なぜ標準は非関数の最終的なリターンを強制しないのですか?void(コンパイラは間違ったreturn値に対してエラーを生成します)

これを強制するためのフラグがgcc/msvcにありますか?(のようなもの-Wunused-result

4

7 に答える 7

13

許可されていません(未定義の動作)。ただし、この場合、規格は診断を必要としません。

return標準では、次のようなコードのために最後のステートメントである必要はありません。

while (true) {
  if (condition) return 0;
}

これは常に0を返しますが、ダムコンパイラはそれを見ることができません。この規格はスマートコンパイラを義務付けていないことに注意してください。ブロックの後のreturnステートメントはwhile、ダムコンパイラが最適化できない無駄になります。この規格では、プログラマーがダムコンパイラーを満たすためだけに無駄なコードを書くことを要求することは望んでいません。

g++-壁は私のマシンで診断を出すのに十分賢いです。

于 2011-06-07T06:08:50.163 に答える
13

-Wallでフラグを使用しgccます。

 warning: control reaches end of non-void function

編集:またはより具体的に-Wreturn-type

于 2011-06-07T05:29:40.500 に答える
3

私の推測:プログラマーはコンパイラーよりもよく知っていることがあるからです。この簡単な例では、何かが間違っていることは明らかですが、多くの値の切り替え、または一般的に多くのチェックを検討してください。あなたは、コーダーとして、特定の値が関数に渡されないことを知っていますが、コンパイラーは、何かが間違っている可能性があることを通知せず、単にヒントを与えます。

#include <iostream>

int foo(){
    if(false)
        return 5;
}

int main(){
    int i = foo();
    std::cout << i;
}

MSVCの警告レベル1でも、次の警告が表示されることに注意してください。

警告C4715:'foo':すべての制御パスが値を返すわけではありません

于 2011-06-07T05:30:34.130 に答える
2

次のコンパイラオプションを使用して、警告をエラーに変換できます。

-Wreturn-type -Werror=return-type

このリンクをチェックしてください

于 2018-07-26T13:36:02.947 に答える
1

明白な答えは次のとおりです。それはエラーではないからです。falseの場合、および呼び出し元が戻り値を使用する場合はエラーに xなりますが、少なくとも一般的なケースでは、どちらもコンパイラーが必ずしも決定することはできません。

returnこの特定のケース(ポインターを返す)では、すべてのパスにを要求することはそれほど難しくありません。Javaはこれを行います。ただし、一般に、C ++ではこれを要求するのは合理的ではありません。C++では、値を作成できない(デフォルトのコンストラクターがないなど)ユーザー定義型を返すことができるため、プログラマーが取得できないことがわかっているブランチでを提供できない可能性がreturn あり、コンパイラはブランチを取得できないと判断できません。

ほとんどのコンパイラは、フローを決定できるときに、そのような場合に警告します。しかし、私が見たものはすべて、最後から抜け出すことが明らかに不可能な場合にも警告を発します。(g++とVC++の両方が警告します:

int
bar( char ch )
{
    switch ( ch & 0xC0 ) {
    case 0x00:
    case 0x40:
        return 0;

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

、少なくとも通常のオプションでは。この関数が決して終わりから外れないことは非常に明白ですが。)

于 2011-06-07T08:11:23.037 に答える
1

AFAIR Visual Studio 2008は、「戻り値のない実行パス」について警告します。「C++はあなたの足を撃つのを止めない」という意味で許可されています。したがって、コンパイラではなく、考える必要があります。

于 2011-06-07T05:26:51.060 に答える
0

この種のプログラミングについて標準が言っていることは、それが未定義の振る舞いを生み出すということです。

未定義動作はC/C ++の喜びと哀れみですが、Cを一種の「高水準アセンブラ」にする低レベルの最適化の多くを可能にする言語設計の基本的な機能でもあります(実際にはそうではありません)。 、しかしあなたにアイデアを与えるためだけに)。

したがって、GCCで使用するスイッチに関するJohnの回答にリダイレクトする一方で、標準がそれを妨げない「理由」を知るために、未定義動作とそのすべてのミステリーの非常に興味深い分析を指摘します。すべてのCプログラマーが知っておくべきこと未定義動作について。それは非常に有益な読書になります。

于 2011-06-07T08:21:02.207 に答える