- ベストアンサー
値を返さないといけないのに、返さない関数の挙動
こんな感じの構造体・関数を作ったとします。 typedef struct personal_info { char name[10]; char address[20]; } personal_t; personal_t getPersonal(int id){;} これには2つのギモンがありまして 1.getPersonalの中は何もせず、値を返さないのに なぜか、コンパイルは通る 2.実行すると、正常に動く いったい、どういう事なのでしょうか。 不思議でたまりません。 どうぞよろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
すでに回答が出ているように、return文で値を返していないときに、呼出し側で返却値を使った場合の動作は未定義です。 問題はここからで、正常動作する可能性は4パターンです。 1. 返却値を捨てている。 2. 返却値を使ったが、コンパイルエラーになることも、シグナルが発生することも、その他実行時エラーが生じることもなく、値がたまたま期待通りであったか、悪い影響を受けるような使い方をしなかった。 3. 処理系が独自仕様として、正常な動作を定義している。 4. 関数を定義しただけで、呼出していない。 質問の文面からすると、おそらく4.に該当するのではないかと思います。
その他の回答 (3)
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
では、ちょっとだけ補足をば。 > その振る舞いは未定義である これを、普通の言葉で言い換えたのが、 「どうなるかはそれぞれのコンパイラ毎に異なる」 になります。 もっとも、「処理系依存」も言い換えると同じ表現 になるので、不親切ではありましたが。 なので、紹介したものは、「あくまでも例」であり、 「こういう動作をした場合」なわけです。 そして、それは、「見かけ上正常に動作した」だけ でもあるわけです。 もちろん、 >一見正常に動作しているように見えても、全く問題 > ありません。 は、このコードが「一見正常に動作しているように見 えても」そのコンパイラは、規格に合致していないと いうわけではなく、「全く問題ない」という意味です。 一見……に見えても、って、「じつはそうじゃない」 という表現なので。
- Tacosan
- ベストアンサー率23% (3656/15482)
ちと ISO を見てみましたが, 「関数の終了の } に到達した (= return 文で何も返さない) ときに, その関数の値を呼び出した方で使ったらその振る舞いは未定義である」 と書いてあります>#1. だから, ここで「正常に動いた」というのは ・返り値を使っていない ・ゴミが入ってるけど結果的に問題なかっただけ の 2通りが考えられます. コンパイルは通るかもしれんけど, 警告くらい出てないかなぁ.
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
それはそういうものだからです……というのが、答えになる のですがそれではあんまりなので。 まず、コンパライラが指摘するエラーは、単に、「文法上の」 エラーに過ぎません。 今のところ、「意味上の」誤りは指摘しません/できません。 この場合、 personal_t getPersonal(int id){;} を見る。 ・personal_t という型は事前に正しく定義されている。 ・関数の宣言として正しい形をしている。 ・関数の実体は、{} で正しく囲まれている ・関数の中身は、 ; という文法的に正しいもの(空文)で 構成されている と、形の上では正解なのでエラーにはなりません。 (警告は出たかもしれません) また、値を返すべき関数が値を返さないときにどうなるかは それぞれのコンパイラ毎に異なるので、一見正常に動作して いるように見えても、全く問題ありません。 具体的な実装では、以下のような例があります(あくまでも例です) ・呼び出し側 1)返値である personal_t 型のサイズの領域を確保する (ここに、関数が返却値をセットする) 2)関数を呼び出す ・関数側 1)本来であれば、呼び出し側が確保した領域に、結果を セットする。今の場合は何もしない ・再び呼び出し側 1)関数の処理が終わったので、あらかじめ確保した領域に 関数からの返値がセットしてあると信じる 2)その領域(今は、何もしてないのでゴミがたまっている) の内容を、変数にコピーするなどして引き取る。 3)その領域を、解放する このような処理を行った場合、見かけ上は無事に動いているよ うに見えるわけです。