このコードを実行するとgccから出力が10になります。なぜgccは私にこの結果を与えますか?
誰かが私に10を与える理由を説明できますか? :)
#include <stdio.h>
int f(int x) {
int y;
y = 2*x;
}
int g() {
int z;
return z;
}
int main() {
int x=5;
f(x);
printf("%d\n",g());
}
このコードを実行するとgccから出力が10になります。なぜgccは私にこの結果を与えますか?
誰かが私に10を与える理由を説明できますか? :)
#include <stdio.h>
int f(int x) {
int y;
y = 2*x;
}
int g() {
int z;
return z;
}
int main() {
int x=5;
f(x);
printf("%d\n",g());
}
:
int g() {
int z;
return z;
}
これは、読み取ります
int g():
reserve memory for an integer, call it z.
return whatever is in that reserved memory.
あなたは、あなたの整数のためにその予約メモリを使用することはありません。その値は、使用する前にそのアドレスにあったもの(または使用しないでください)です。その価値は何でもかまいません。
他の機能でも同じことを行います。あなたがやっていることは、初期化されていないメモリを読むことです。あなたはそれ以上の情報のためにそれをgoogleすることができます。 「スタック」と「ヒープ」、動的メモリ、およびその他の関連トピックも参照してください。
それは私のために物事をクリア。ありがとう。 :) – Gaui
これは値が設定されていない変数を参照しています。おそらく、コンパイラがf()の変数に同じメモリ位置を使用しているため、コンパイラは10を返しますが、それは保証されていないため、依存してはならず、好奇心に過ぎません。
グラムは場所が最後のセットを説明するために何もないあなたに、X * 2 = 10
のあなたの答えを与えるF関数であったことをあなたの例では、スタックから初期化されないvarableを返します。最初のf
は、int
を返すと宣言されていても何も返さず、g
は初期化されていない値を返すため、コードは未定義の動作をします。
実際には、関数がコールスタックの上に置かれる方法はprintf
コールにg()
の戻り値と同じ場所にあるように(最終的に値10
を有する)ローカルy
を引き起こしてしまうので、あなた値10
が表示されます。しかし、それは多かれ少なかれ運の問題です。
厳密に言うと、関数の値は使用されていないので、 'f()'は未定義の振る舞いをしません。しかし、それは明らかに問題の領域です。 –
@MichaelBurr:非void関数から値を返さないという漠然とした考えは、後でその関数の戻り値を使うだけでなく、すでにUBです。私はチェックしなければならないだろう。また、CはC++と異なる点もあります。 –
あなたはzを初期化していないので、スタック上の同じ場所をyとして使用しているためです。初期化していないので、古い値はまだそこにあります。
これは、人々が最適化を恐れている理由と、彼らが上司にコンパイラのバグを見つけようとしていることに自信を持っている理由の完全な例です。このコードは他の人が暗示しているように、g()
に初期化されていない変数を使用することに関する警告を表示します。あなたのコンパイラ設定では、それはf(5)
への呼び出しからスタック上の古い値を使用しています。異なるコンパイラの最適化設定では、変数がスタック上でどのように終わるかに影響を与える可能性が高く、変更を加えても関係のないように見える場合は別の結果になります。これは未定義の動作であり、結果がどのような値になるかは保証されていませんが、通常は呼び出し順序を理解してコンパイラがスタックを設定する方法で説明するのは簡単です。このような奇妙な動作をトラブルシューティングしているときに警告が表示される場合は、まず警告を修正してから、理由を質問してください。
-Wall、IMOなしでCプログラムをコンパイルしないでください。 –