- 締切済み
C,C++に変数の初期化と処理系について
C,C++で変数宣言したけれども初期化しないで使った場合、何らかの値を出力してしまう場合とかエラー(core dumpなども)を出して停止する場合など処理系依存ということになると思います。また、別言語ではデフォルトでゼロ指定される場合もあります。これは自動初期化とい意味で初期化がされているものに分類されます。 処理系で初期化しないで変数を利用して適当な値を出すという風になっているとしたらその理由とかメリットというのがあるものでしょうか。core dumpで処理が停止するというのは当然であり、良心的とも言えるわけで、適当な値を出すことは危険極まりないと思うのですが。 Windowsで、分子・分母の変数を定義しないで割り算したところ、256な数値が出ました。 Linuxではcore dumpになるところだと思います。 初期化して使え、ということを徹底するべきですが、逆に初期化しないでも(すなわち変数としてどのアドレスに対応しているか不明であっても?)計算を進めてしまうメリットがどこかにあるのか?という疑問が生じます。 いかがでしょうか。そこが分かれば尚更変数を初期化して使う習慣が身に着くと思うわけですが。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
>処理系で初期化しないで変数を利用して適当な値を出すという風になっているとしたらその理由とかメリットというのがあるものでしょうか。 第一のメリットは「初期化を行なうコードが不要」と言う点にある。 例えば「宣言した時に、自動的に何かに初期化される」という場合、 void sub(void) { int a; a = UserFunction(0); printf("%d\n",a); } というプログラムを書いた場合「初期化するコードが常に実行されてしまう」という仕様であれば、その「初期化コード」は「完全に無駄なコード」になってしまう。 上記のようなプログラムが「1回のプログラム実行に付き、1000万回呼ばれる」としたら「1000万回、無駄な初期化を行なう」ことになり、CPUを無駄使いしてしまう。 >Windowsで、分子・分母の変数を定義しないで割り算したところ、256な数値が出ました。 >Linuxではcore dumpになるところだと思います。 その認識は間違っている。 WindowsもLinuxも、メモリ管理は「似たり寄ったり」であり、ほぼ同一である。 まず、C言語においての「変数」は、その変数の「記憶クラス」により、以下のいずれかのメモリに配置される。 ・グローバル変数、staticによりスコープを制限したグローバル変数、staticが付いたローカル変数で、定義時に初期化している物 メモリ中の「データセグメント」に置かれる。 データセグメントは、プログラムがメモリに配置される際に、一度だけ「初期化する値」で初期化される(初期化値はスタートアップ時に1度だけプログラムファイルからロードされる) ・グローバル変数、staticによりスコープを制限したグローバル変数、staticが付いたローカル変数で、定義時に初期化していない物 メモリ中の「BSSセグメント」に置かれる。 BSSセグメントは、プログラムがメモリに配置される際に、一度だけ「0」で初期化される(プログラムロード時に1度だけ0クリアされる) ・auto属性が付いた変数、及び、関数内の局所変数 メモリ中の「スタックセグメント」に置かれる。 スタックセグメントは、プログラムがメモリに配置される際に、一定のサイズが確保されるだけで、一切、初期化は行なわれない。 定義時に初期化されている場合は、関数またはブロックが実行されるたびに初期化される(初期化を行なう実行コードが生成される) 定義時に初期化されていない場合は、値は不定。 なので、WindowsもLunixも「未初期化の局所変数」は「値が不定」になるのは同じである。
- hiodraiu
- ベストアンサー率15% (451/2846)
初期化しないのは、何かしらのメリットのためというよりは、単に何もしないという言語仕様だということだと思いますよ。せいぜい処理速度が初期化が無い分だけ早くなるぐらいじゃないですか。それでも昔のコンピュータなら恩恵はありそうですね。何せC言語は古い言語ですから。 そもそも変数を使用する際には、コードで何かしらの初期値を設定するわけですよね。だったら初期値をコンパイラが決め打ちする必要もないですよね。変数の型に応じた初期値を持つメリットのほうが少ないとも考えられませんか?数値型の初期値が0は使い道もありそうですが、ポインター型の初期値がNULLになっちゃうと、そのままでは絶対に使えないわけですから、何かしらの値を設定するコードが必要ですよね。
- wormhole
- ベストアンサー率28% (1626/5665)
>Linuxではcore dumpになるところだと思います。 たまたま分母になる変数が0だった場合には、core dumpしますが、そうでない場合にはしません。 分母の変数が初期化されていないのを認識してcore dumpしているわけではありません。
- notnot
- ベストアンサー率47% (4900/10358)
処理系が暗黙の初期化をしないメリットは、実行コードが短くなることです。 int x; ~~この間でxへの参照は無し x=10; で、宣言の時点で0に初期化すると、参照する前に他の値が代入されると、初期化のコードが無駄になります。 あと、intの場合で言うと0への自動初期化機能があるとすると、0だけ特別扱いするのは変ですね。 初期値が0の時だけ明示的に初期化を書かなくていいが、0以外の場合は明示的に初期化を書くというのは変です。 なお、変数を初期化しないことで異常終了することがあるのは、未代入変数の値をアドレス値としてそのアドレス内容にアクセスする場合だけでしょう。例えばポインタの場合。 学習用とか、テスト用の特別な処理系であれば、未代入変数の参照をエラーとして検出することも可能なものもあるでしょう。 あまり一般的で無いと思いますが、私は(コーディングルールがない場合)、宣言と同時の代入つまり、int x=3; のような書き方は原則としてしません(const intならするかも)。変数への初期化は、初期化すべきタイミングで実施すべきで、用途の違う変数を関数先頭で一斉に初期化するのは変だと思うからです。
お礼
回答ありがとうございます。先日実際にやってみたら、よく見たら変な値なのですが、穏便な程度の値(例えば答えが24ぐらいのところを278などが出る)なのでそうかもしれないと思ってしまいそうです。私はシミュレーション風のことをやっているので間違ったら1.286e+10という感じの数値が出てくるのです。だからあの程度の値を出されたら間違ったまま素通りしそうなのです。