• ベストアンサー

staticで初期化した変数(?)を使って初期化

次の3つのプログラム、1番目はコンパイルエラーになりますが、下2つはエラーになりません。1番目のプログラムのエラーメッセージ:初期化子が定数ではありません。 処理系にかかわらずそうだとしたら、その理由はなんでしょうか。 ---------------------------------- int main(void) { static int a=5; static int b=a; return 0; } ---------------------------------- int main(void) { static int a=5; int b=a; return 0; } ---------------------------------- int main(void) { int a=5; int b=a; return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • nagare
  • ベストアンサー率33% (280/831)
回答No.2

staticは、実行時にその領域を初期化するのですが、その値が変数だとわからない ので、定数のみ ということです。 でも、これはコンパイラ依存があるかも(MS-Cしか知らないので。。。) static int b=a;をコンパイルできる、できないの話は、コンパイラとアセンブラの話になってしまいますので、この辺で話は切っておきます。 staticの仕組みは、アセンブリして、アセンブラを見れば一発!

noname#2045
質問者

補足

>staticは、実行時にその領域を初期化するのですが、その値が変数だとわからないので、定数のみ ということです。 そうですね、「staticの変数を初期化する場合は、定数でなければならない。」という規則があると考えるべきなんですね。 アセンブラについてはよくわからないので、やめておきます。 ありがとうございました。 ------------------------------- 質問者用メモ欄 static const int a=5; static int b=a; と、aにconstをつけてもコンパイルエラーは消えない。 constを付けたからといって定数ではない。

その他の回答 (2)

回答No.3

> そうですね、「staticの変数を初期化する場合は、定数でなければならない。」という規則があると考えるべきなんですね。 static以外にも構造体、共用体、配列の初期化も定数式でなければなりません。 この手のことは、処理系を動かして調べるより(処理系独自の拡張があるので)ANSIなりJISの規格を見るのが間違いないかと。 JISでしたら、 http://www.jisc.go.jp/ のデータベースから「X3010」で閲覧することができます。

参考URL:
http://www.jisc.go.jp/
noname#2045
質問者

お礼

JIS X3010の文書をダウンロードして、見ました。 「6.5.7初期化」というところに次のように書いてありました。 「静的記憶域期間をもつオブジェクトの初期化子、または集成体型若しくは共用体型をもつオブジェクトの初期化子の並びにおいて、すべての式は定数式でなければならない。」 集成体型とは、配列と構造体のことですから、まさしくご回答のどおりのようです。 今回の質問は静的記憶域期間を持つ場合なので、それは解決したということでいいのですが。。 この文でよくわからないのは、 「自動記憶域期間を持つ構造体や配列を、関数の仮引数を使って初期化してはならない。」 という意味まで含んでいるのか、です。 「集成体型...をもつオブジェクトの初期化子の並びにおいて、すべての式は定数式でなければならない」ってウソだろ・・・ そもそも定数式って? と思ったんですが、今回の質問については解決したので回答は締め切り、自分で調べた上でわからなければ改めて質問します。

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.1

単なる推測ですが。 間違いが起きやすいので、コンパイラーが「親切心」でチェックして くれているのではないかと思います。 単なるintならその関数が実行されるたびに変数確保と初期化が行なわれます。 ところが、staticでは1回目の実行時だけ変数確保と初期化を行ないます。 その関数が実行終了しても変数は消滅せず、次回の実行に引き継がれます。 (main関数だけは毎回初期化されるという特例があるかも?・・・自信なし) static int b=a; は、1回目の実行開始時だけ保証され、aかbを一度書き換えると、そのあと (b==a)が保証されなくなります。 関数の起動ごとに(b==a)になるという勘違いを防ぐためと言う気がします。

noname#2045
質問者

補足

ありがとうございました。 なるほどなあと思いました。 2番目のプログラムでは、bの宣言時には a==b になっていますね。 (aが他の場所で書き換えられる可能性まで考えれば、値は5とは限らないけれど。) けれども、勘違いを防ぐためなら、警告ぐらいにとどめておいてほしいです。

関連するQ&A

専門家に質問してみよう