次の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;
}
No.2ベストアンサー
- 回答日時:
staticは、実行時にその領域を初期化するのですが、その値が変数だとわからない
ので、定数のみ ということです。
でも、これはコンパイラ依存があるかも(MS-Cしか知らないので。。。)
static int b=a;をコンパイルできる、できないの話は、コンパイラとアセンブラの話になってしまいますので、この辺で話は切っておきます。
staticの仕組みは、アセンブリして、アセンブラを見れば一発!
この回答への補足
>staticは、実行時にその領域を初期化するのですが、その値が変数だとわからないので、定数のみ ということです。
そうですね、「staticの変数を初期化する場合は、定数でなければならない。」という規則があると考えるべきなんですね。
アセンブラについてはよくわからないので、やめておきます。
ありがとうございました。
-------------------------------
質問者用メモ欄
static const int a=5;
static int b=a;
と、aにconstをつけてもコンパイルエラーは消えない。
constを付けたからといって定数ではない。
No.3
- 回答日時:
> そうですね、「staticの変数を初期化する場合は、定数でなければならない。
」という規則があると考えるべきなんですね。static以外にも構造体、共用体、配列の初期化も定数式でなければなりません。
この手のことは、処理系を動かして調べるより(処理系独自の拡張があるので)ANSIなりJISの規格を見るのが間違いないかと。
JISでしたら、
http://www.jisc.go.jp/
のデータベースから「X3010」で閲覧することができます。
参考URL:http://www.jisc.go.jp/
JIS X3010の文書をダウンロードして、見ました。
「6.5.7初期化」というところに次のように書いてありました。
「静的記憶域期間をもつオブジェクトの初期化子、または集成体型若しくは共用体型をもつオブジェクトの初期化子の並びにおいて、すべての式は定数式でなければならない。」
集成体型とは、配列と構造体のことですから、まさしくご回答のどおりのようです。
今回の質問は静的記憶域期間を持つ場合なので、それは解決したということでいいのですが。。
この文でよくわからないのは、
「自動記憶域期間を持つ構造体や配列を、関数の仮引数を使って初期化してはならない。」
という意味まで含んでいるのか、です。
「集成体型...をもつオブジェクトの初期化子の並びにおいて、すべての式は定数式でなければならない」ってウソだろ・・・
そもそも定数式って?
と思ったんですが、今回の質問については解決したので回答は締め切り、自分で調べた上でわからなければ改めて質問します。
No.1
- 回答日時:
単なる推測ですが。
間違いが起きやすいので、コンパイラーが「親切心」でチェックして
くれているのではないかと思います。
単なるintならその関数が実行されるたびに変数確保と初期化が行なわれます。
ところが、staticでは1回目の実行時だけ変数確保と初期化を行ないます。
その関数が実行終了しても変数は消滅せず、次回の実行に引き継がれます。
(main関数だけは毎回初期化されるという特例があるかも?・・・自信なし)
static int b=a;
は、1回目の実行開始時だけ保証され、aかbを一度書き換えると、そのあと
(b==a)が保証されなくなります。
関数の起動ごとに(b==a)になるという勘違いを防ぐためと言う気がします。
この回答への補足
ありがとうございました。
なるほどなあと思いました。
2番目のプログラムでは、bの宣言時には a==b になっていますね。
(aが他の場所で書き換えられる可能性まで考えれば、値は5とは限らないけれど。)
けれども、勘違いを防ぐためなら、警告ぐらいにとどめておいてほしいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- C言語・C++・C# プログラミングペーパーテスト 次の問題の実行結果を答えろ #include int x[ ] = { 1 2022/06/16 21:49
- C言語・C++・C# プログラミングの授業のペーパーテスト 実行結果を答えろ #include int x[ ] = {1 3 2022/06/16 20:08
- C言語・C++・C# プログラムの時、フローチャートはどうなりますか?図でお願いします。 int main(void) { 1 2022/10/01 22:45
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# int tff(int clk) { static int state = 0; //状態 stat 1 2022/07/11 21:14
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エラー「invalid conversion fr...
-
DWORDの実際の型は何でしょうか
-
相互参照するクラス、俺こんな...
-
構造体の要素すべてに対する四...
-
【#define】 defineで定義した...
-
long型の定数の末尾にLを付ける...
-
構造体を引数とする、クラス間...
-
C言語のreturnの使い方
-
構造体の宣言でエラーが出ます。
-
typedef enumの使い方を教えて...
-
0除算を判定したい
-
不正な構造体の演算
-
C言語でのフィボナッチ数列の表示
-
変数の型を定義しなかった場合...
-
2÷3などの余りについて
-
Enterキーを押されたら次の処理...
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語を実行すると-infが出てき...
-
std::set<int> で、ある値が何...
-
Aの値からBの値を除するとは??
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
typedef enumの使い方を教えて...
-
C++のfor文について
-
long型の定数の末尾にLを付ける...
-
2重定義って??
-
関数の実体定義にヘッダファイ...
-
main.c:7:43: warning: implici...
-
変数の型を定義しなかった場合...
-
visualstudio C# テキストボッ...
-
ハンドルされていない例外が発...
-
C++でboolにintの値を代入する...
-
enumについて
-
構造体の宣言でエラーが出ます。
-
【#define】 defineで定義した...
-
C++ クラスをメンバにもつクラ...
-
0除算を判定したい
-
構造体の要素すべてに対する四...
-
値を返り値に返すのと参照渡し...
-
namespace定義の使い方
-
GCCで暗黙の型変換の警告を出し...
おすすめ情報