「戻る」コマンドなしで戻る


8

gccでコンパイルされたCプログラミング言語、WSLのターミナルbash

配列内で最小の数を見つけるために再帰関数を記述しましたが、これは問題なく機能します。

/*01*/    int minimo(int array[], int n)
/*02*/    {
/*03*/      static int min = 0;
/*04*/    
/*05*/      if (n == N)
/*06*/      {
/*07*/          return array[n-1];
/*08*/      }
/*09*/      else
/*10*/      {
/*11*/          min = minimo(array, n+1);
/*12*/          if(array[n]<min){
/*13*/              min = array[n];
/*14*/          }
/*15*/      }
/*16*/    }

唯一の問題は、呼び出し側に「min」を返さないため、機能しないことです...

int main()
{
    //Var
    int array[N] = {10, 2, 5, 1, 7};
    printf("Min: %d\n", minimo(array, 0));
}

私の懸念は実際には問題ですが、関数がそのまま正常に機能する私のマシンではありません。それは私の友人のラップトップとIDEでの問題です。友人のMacbookでXCodeにコピーしてみましたが、「return min;」という行では機能しません。関数の最後に追加されませんでした。

15-16行目の間で追加する必要があります return min;

/*15*/      }
            return min;
/*16*/    }

あなたへの私の質問は次のとおりです。

  1. 関数が変数を自動的に返すにはどうすればよいですか?
  2. 私が作成した唯一の変数(static int min)を返すことは可能ですか?
  3. それとも、変数が持つ静的属性に関連する「問題」ですか?
  4. 関数の性質(再帰的)と関係がありますか?

これは私の最初の投稿です。フォーラムのルールに違反している場合は、親切にしてください。


SOの質問を読みます:stackoverflow.com/q/204476/8339821と回答。これにより、main関数が何を返すかがわかります。
yvw

一見すると、gcc固有ではなく、WSL固有のように見えます。WSLが自動的に「考え」、自分でコードを修正するようです。
RobertSは

@ЯрославМашкоこれは完全に異なるものであり、この質問とは関係ありません。問題mainは、それの戻り値についてではなく、特定の実装における関数の「自動」戻り値についてです。
RobertSは

@RobertSsupportsMonicaCellioええ、あなたは正しいです。私はもう一度質問を読み、SOが彼の機能が実際に何を返すのかを知りたいと思った。彼はどういうわけかメインからの復帰を逃したと思いました。次に、この回答は件名に関する完全な情報を提供します:stackoverflow.com/a/1610454/8339821。重要な点はC、returnステートメントがない場合、特定の標準がゼロを返すことです。
yvw

-Wallスイッチを使用してファイルをコンパイルし、コンパイラが何を通知するかを確認する必要があります。
yvw

回答:


5

私の懸念は実際には問題ですが、関数がそのまま正常に機能する私のマシンではありません。それは私の友人のラップトップとIDEでの問題です。友人のMacbookでXCodeにコピーしてみましたが、「return min;」という行では機能しません。関数の最後に追加されませんでした。

未定義の動作の典型的な例。あるマシンでは機能しますが、別のマシンでは機能しません。昼間は機能しますが、夜間は機能しません。あるコンパイラーでは機能しますが、別のコンパイラーでは機能しません。未定義の動作を呼び出す場合、C標準では、コードの動作に関する要件はありません。

C11標準6.9.1.12

関数を終了する}に到達し、関数呼び出しの値が呼び出し元によって使用される場合、動作は未定義です。

あなたのコードでは、まさにそれが起こります。戻り値を出力しようとすると、未定義の動作が呼び出されます。

多くの人が信じていることに反して、非void関数ではreturnステートメントを完全に省略できます。存在しない戻り値を使用しようとした場合にのみ、未定義の動作になります。

これを回避するには、常に少なくともでコンパイルしてください-Wall -Wextra


そして、忘れないでください-Werror
Jonathon Reinhart

@JonathonReinhartさて、それはビールを必要とする一種の議論です。:)
klutt

1
@JonathonReinhart重要なのは警告を実際に気にすることです。コーダーが気にせず、-WerrorSO を使用している場合、「なぜこれがコンパイルされないのですか?」それがなければ「なぜこれは奇妙な振る舞いをするのですか?」そのパラメーターは良いことだと私は同意しますが、それはある程度ターゲットを逃します。
klutt

1
私の気持ちは、ある-Werrorユーザーがされているため、このような不要なSOの質問防止強制彼らは実行するために壊れた実行可能ファイルを持っていないときの警告を気にする:-)
ジョナサン・ラインハルト

2
たぶん、GCCはデフォルトで、Stack Overflowテーマと埋め込まれた検索結果を含むHTML形式のエラーメッセージを表示するだけです
Jonathon Reinhart

2

関数が変数を自動的に返すにはどうすればよいですか?

プロトコルに従います。それは、関数の戻りがどこかの場所で戻り値を見つける必要があることを知っておりreturn、その関数からの明示がその場所を埋めます。を呼び出さない場合return、指定された場所にランダムな値が保持されます。

私が作成した唯一の変数(static int min)を返すことは可能ですか?

いいえ、何が返されるかは未定義です。それは何でもかまいません。

それとも、変数が持つ静的属性に関連する「問題」ですか?

繰り返しになりますが、返されるものは未定義です。

関数の性質(再帰的)と関係がありますか?

はいといいえ。関数が外部として定義されている場合、戻り値は静的関数の場合と同様に別のプロトコルに従います。

それは最終的なコードで何でも起こりえます、C言語はそれが再帰的かどうかにかかわらず、関数を実装する方法を課しません。たとえば、関数が再帰的で事前計算できる場合は、呼び出しの場所で最終値のみを置き換えることができます。これは、プログラムの最終結果が期待される結果であり、Cを定義する運用上のセマンティクスに準拠しているため、時間としても正しいISO9899です。

私は公式文書から引用します:

4抽象マシンでは、すべての式がセマンティクスで指定されたとおりに評価されます。実際の実装では、その値が使用されておらず、必要な副作用(関数の呼び出しや揮発性オブジェクトへのアクセスによるものも含む)が発生していないと推定できる場合、式の一部を評価する必要はありません。

また、呼び出しをその呼び出しの値で置き換えることもできますが、これは正しいことです。

したがって、すべての質問で、答えは未定義の動作です。


1

関数が変数を自動的に返すにはどうすればよいですか?

私はたまたま起こり、min変数はたまたまABIの正しい戻りレジスターにあります。

私が作成した唯一の変数(static int min)を返すことは可能ですか?

関数の終了直前に使用された方が関係していると思いますが、私はここで推測しています。これはC言語で定義された動作ではなく、偶然に機能しました。

それとも、変数が持つ静的属性に関連する「問題」ですか?

関数の性質(再帰的)と関係がありますか?

これは偶然の振る舞いだったので、そうであったかもしれません。ランダムと決定論の違いは、説明をあきらめるほど多くの変数があることです。


-3

あなたはどこかでNを定義したと思います(おそらくあなたの場合はN = 5)。

ほとんどのコンパイラは、returnステートメントがない場合、自動的に「return 0 "ステートメントを追加します。

*詳細についてはコメントを参照してください。実際には未定義の動作です*

再帰関数では、配列の残りの長さを渡し、n == 0に達したときに停止することをお勧めします。

グローバル変数を調べたり、関数内で定義したりしないでください。

int minimo(int array[], int n)
{
  ...
  if (n == 0)
  ...
            min = minimo(array, n-1);
  ...
}

(その他の変更が必要です)

実際には、メイン関数でのみ配列の長さを知っている必要があるため、次のように呼び出します。

printf("Min: %d\n", minimo(array, N));

5
番号!main()C99(またはそれ以降)の実装return 0;前のreturnステートメントがない場合にaが追加される)を除いて、失敗returnはUBです。
pmg

@pmgをSOのどこかで読みましたが、その表現はに変わりC89ます。そして、それは私が今日得ることができる最低限です。
yvw

@ЯрославМашко:C89にはデフォルトの戻り値に関する記述はありません。C99(およびC11でも同様):「メイン関数を終了する }に到達すると、値0が返されます。」(強調は私のものです)
pmg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.