• ベストアンサー

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; }

noname#2045
noname#2045

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

  • ベストアンサー
  • 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

  • static 変数について

    static 変数について 今、C++を勉強しているのですか、static変数がどのように動くのかよくわかりません。 下のプログラムのint a はローカル変数だから、ブロックを抜けたら、初期化されるためstatic変数にして、ブロックを抜けても値を保持するようにすってことはわかるのですが 毎回このブロックに入る度、static int a = 0;を読むことになり、その前に入っていた値はなくなるのではないでしょうか?それとも,static int a と書かれていると,1度しか実行されないから、値が保持され続けるのでしょうか? int add (int x ) { int a = 0; a += x; return a; }

  • static付き宣言の初期化

    static付きの宣言をした場合の変数の初期化について教えてください。(ANSI-C) int func(void) { static int si; static char sca[10]; static char *scp; /* 何らかの処理 */ return 0; } このように関数内でstatic付きで宣言したとき、変数はどのように初期化されますか? siは0、sca[0]からsca[9]までは'\0'、scpはNULLで初期化されますか? また、このようなstatic付きの宣言が関数の外にあった場合は、どのように初期化されますか?

  • static変数の扱いについて

    例えば、下記のような場合、 main(){ ・・・ while(A==B){ kakunin1();//この関数を何度か繰り返し呼び出す } } int kakunin1(){ static int sample = 0.0; kakunin2(&sample); sample++; //(1) return(sample); } void kakunin2(*sample){ *sample++; //(2) } まずはじめに(2)でsample=1になって、 次に(1)で2になって、 今度mainからkakunin1がコールされると、sampleの値は2を 保持しているのでしょうか?つまりその後(2)でさらにsample=3と なるのでしょうか?

  • 変数の初期値

    へんてこな質問かもしれません・・・ class Syokika{   public static void main(String args[]){     int[] a = new int[1];     System.out.println(a[0]);   } } を実行するとどうなるかという問題なのですが、 「変数が初期化されていない」 というエラーが出ると思っていたのですが、 答えは「0と表示される」でした・・・ で、解説を見ると、「配列が生成されるときに初期値が生成される。intの場合は0だ」と書いてありました。 でも、たんにint a;とした場合にaを参照しようとすると初期化されてないですよね・・・? これはどういうことなのでしょうか・・・?

    • ベストアンサー
    • Java
  • static変数のループ内での処理

    以下のc++ソース内で、static int b = 100;という式ですが、 1回目に、ここの処理を通ったときに静的変数が作成されると思います。 2回目のループのときに、ここでまたb=100と初期化されています。 ですが、ループを重ねるごとに、カウントが1増えていきます。 staticなので、これは期待通りの動作だとは思うのですが、なぜそうなるのかがわかりません。 コンパイラなどが、staticが頭に付いたものは、2度目のループ以降はこの行を無視するように しているのでしょうか? もしそうなら、他に暗黙のルール?のようなことが他にもあるのでしょうか? 考えるとさらにc++がわからなくなってきました。 #include <windows.h> #include <iostream> using namespace std; void test(){ int a = 100; cout << a << " " << &a << endl; static int b = 100; cout << b << " " << &b << endl; b++; int * abc = new int [10]; abc[0] = 9999; cout << abc <<" "<< &abc << " " << abc[0] << endl; delete [] abc; } int main(){ while (1){ Sleep(2000); test(); } } 教えてください。 よろしくお願いいたします。

  • forループの中での初期化

    http://www.okweb.ne.jp/kotaeru.php3?q=802781 すいません。またわからなくなってしまいました。 class Fooo{   public static void main(String args[]){     int a;     int b=10;     int c;     for(int i=0;i<5;i++){       a=10;       c=b+i;       System.out.print(c);     }     System.out.println(a);   } } 初期化は「確実に」行われていますよね? aが初期化されてない、というコンパイルエラーが出るのです・・・ なぜですか???

    • ベストアンサー
    • Java
  • 関数外からstatic変数を再度初期化できるのでしょうか?

    以下の静的変数?についてA,Bのメモリは別でしょうか? test関数外からBの変数を再度初期化できるのでしょうか? staticの仕組みがわからないのでstaticのメモリの初期化のタイミングとメモリアクセス方法について知りたいです。 static x = 1; // ---A int test() { static int x = 0; // --- B } またexternの働きも知りたいです。

  • mainクラス内に書いたメソッドの宣言の仕方(staticの必要性)

    java を勉強中の超初心者です、宜しくお願いします。 main と同じクラスに disp というメソッドを作成してやり、” void disp(int a , int b )”と書いてやりましたが、mainからアクセス出来ません。 そこで、” static void disp(int a , int b )” という風に” static ” を先頭につけてやりましたら、うまく動きました。 これは、mainメソッドから他のメソッドにアクセスする場合には、必ず” static ” をつけてやる必要があるということでしょうか。 ======================================================= class クラス練習 { public static void main(String[] args) { disp(5,10); } /*static*/ void disp(int a , int b ) { System.out.println("a+b = " + (a+b)); } }

    • ベストアンサー
    • Java
  • グローバル変数について

    ◎1--------------------------------- #include<stdio.h> void func(void); int glb; int main(void) { int a=20; glb=30; printf("main a=%d glb=%d\n",a,glb); func(); return 0; } void func(void) { int b=88; printf("func b=%d glb=%d\n",b,glb); } ------------------------------------- ◎1の実行結果----------------------- main a=20 glb=30 func b=88 glb=30 ------------------------------------- ◎2--------------------------------- #include<stdio.h> void func(void); int glb; int main(void) { int a=20; func(); printf("main a=%d glb=%d\n",a,glb); return 0; } void func(void) { int b=88; int glb=30; printf("func b=%d glb=%d\n",b,glb); } ------------------------------------- ◎2の実行結果----------------------- func b=88 glb=30 main a=20 glb=0 ------------------------------------- 以上2つのプログラムで、◎1は参考書を参考に作成したものです。 ◎1のプログラムで、グローバル変数glbの値をmain( )関数内で設定していたので、次に◎2のようにfunc( )という関数プロトタイプ内で、グローバル変数glbの値を設定し、main( )関数内のprintf文でも表示させようと思ったら、「glb=0」となってしまいました。 なぜこのようになってしまうか、教えてもらえたら嬉しいです。

  • コンパイルしたところ、void incの"V"のところで「式の開始が不

    コンパイルしたところ、void incの"V"のところで「式の開始が不正です。」のエラーメッセージになってしまいます。 お教えください。 public class test12{ public static void main(String[] args) { int a=5; int[] b = {7}; void inc(int a) { a++; } void add(int[] b){ b[0]+=3; } System.out.print(a+b[0]); } }

専門家に質問してみよう