- ベストアンサー
c言語の初期化について
#define TMAX 100 int a[TMAX]; static int b[TMAX]; void main() { int c[TMAX]; static int d[TMAX]; } 上記、a,b,c,dの配列の要素において、未初期化の状態で0が保証される物はありますか? また、宣言時に初期化 (a[TMAX]={0,0,0・・・0}) をする場合、0を100個書かなければなりません。 また、TMAXの値が変わるたびに書き換えなくてはなりません。 TMAX分、全て同じ値で初期化してくれる、便利な記述方法などありませんでしょうか? よろしくお願いします。
- みんなの回答 (14)
- 専門家の回答
質問者が選んだベストアンサー
まず、mainの返却値の型がvoidなので、特に処理系がそれを許していない限り、動作が未定義になります。したがって、何一つ保証されません。 次に、a, b, dについては、静的記憶域期間を持つオブジェクトですので、(mainの問題さえなければ)0で初期化されることが保証されます。ただし、スタートアップも自分で実装しているのであれば、実質的には自分で保証することになります。 dに関しては、自動記憶域期間を持つオブジェクトですので、初期値に関しては何の保証もありません。 C++でnewで割付けた場合でも、自分でそのように再定義したのでなければ、初期値は不定です。 なお、今回は配列の要素がintなので問題ありませんが、ポインタや浮動小数点型を含む場合、memsetでクリアしても、各要素がNULLや0.0になることは保証されません。
その他の回答 (13)
- jacta
- ベストアンサー率26% (845/3158)
#8について... > mainの返り値型によって処理系の動作が変わるという話は初めて聞きました。 そうではなく、mainの返却値はintでなければならないということです。 http://www.kijineko.co.jp/tech/superstitions/void-main.html > 0が保証されるのは、 > グローバル× > グローバルスタティック○ > ローカル○ > ローカルスタティック○ > という認識で良いのでしょうか? 間違っている部分は#13で指摘されているとおりです。 関数の外と内では、static指定子の意味が微妙に異なるので注意してください。関数の外では、staticがあろうがなかろうが、常に静的記憶域期間を持ちます。staticが付くと内部結合になるだけです。 そして、静的記憶域期間を持つ場合に限り、ゼロ初期化が保証されます。 #11について... > いまは、Visual Studio.NET 2003は使っていないのですが、 > 何かのときに役立てればと思っております。 Visual Studio 2005でもVisual Studio 2008でも事情は同じです。 特定処理系に依存する特別な理由がない場合は、移植性の高いコードを書く習慣を身につけましょう。
- titokani
- ベストアンサー率19% (341/1726)
> グローバル× > グローバルスタティック○ > ローカル○ > ローカルスタティック○ グローバル○ グローバルスタティック○ ローカル× ローカルスタティック○ です。 ローカルの初期化はちょっと特殊で、 int c[TMAX]={1}; だと、先頭が1で残りがゼロになりますが、 int c[TMAX]; だと、一切初期化されず、不定の値になります。 一方、グローバル変数などは、 int a[TMAX]; static int b[TMAX]; static int d[TMAX]; と、初期化要素を一切書かなくても、ゼロで初期化されることが保証されています。 memsetはおっしゃる通り、使わないほうがいいでしょう。 ゼロ初期化ならば、なんとか使えなくもないですが、結局intの1で初期化したい場合とかには使えませんしね。
お礼
すみません、読み違えていました。 訂正ありがとうございます。 static global local の特性について、 詳しく教えていただきまして、ありがとうございます。
- tyatsumi
- ベストアンサー率58% (30/51)
ANo.5間違ってました orz memset(a, 0, TMAX * sizeof(int)); にしないと埋め尽くされませんね。 あと、型を無視している点でも不適切な回答だったようです。 ごめんなさい。
お礼
訂正ありがとうございます。 memsetの記述って単純なんですが、何故か覚えられません。 いちいちヘルプを見ている気がします。。
- jacta
- ベストアンサー率26% (845/3158)
#9さんが紹介されている http://oshiete1.goo.ne.jp/qa2727121.html の回答はあまり適切ではないかと...。 というのも、あちらの回答はVisual Studio.NET 2003に特化しているからです。 ZeroMemoryは非標準関数なので一般的には使えませんし、第一memsetと同じ問題を持っています。bzero等の関数も同じことがいえます。
お礼
補足ありがとうございます。 いまは、Visual Studio.NET 2003は使っていないのですが、 何かのときに役立てればと思っております。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
ちょっと補足です。 No.6 で書かれているのは、「正解」です。 ただし、ちょっと誤解しやすいのは、 int a[TMAX]={1}; と書いた場合、一見全要素が '1' になりそうな気がしますが、実は、a[0] だけが、1 になって、残りはゼロになります。 実際には、配列要素の数より初期化リストの数が少ない場合、残りの配列要素は暗黙のうちにゼロで初期化されるということになっています。 int a[TMAX]={0, 1, 2}; は、a[0] = 0, a[1] = 1, a[2] = 2, その他はゼロです。 int a[TMAX]={0}; の場合、a[0] が(指定された)ゼロで初期化され、それ以外の要素は(暗黙のうちに)ゼロで初期化されます。 結果的に、全要素が0で初期化されることになります。 ちなみに、C++の new も対応するクラスのコンストラクタで明示的に初期値 を設定しない限り、new が暗黙のうちに初期化してくれると言うことはありませ ん。
お礼
補足ありがとうございます。 疑問点解消できました。 "暗黙的に0で初期化"されるならば、動作に納得です。 0以外に初期化したい場合は、明示的に回さないとダメみたいですね。
以下を見れば解決します。 構造体の初期化方法について http://oshiete1.goo.ne.jp/qa2727121.html
お礼
ありがとうございます。 リンク参考にさせていただきました。
- jacta
- ベストアンサー率26% (845/3158)
すみません。一箇所まちがいました。 × dに関しては、自動記憶域期間を持つオブジェクトですので、初期値に関しては何の保証もありません。 ○ cに関しては、自動記憶域期間を持つオブジェクトですので、初期値に関しては何の保証もありません。
お礼
ありがとうございます。 mainの返り値型によって処理系の動作が変わるという話は初めて聞きました。 この点がクリアだとした場合、0が保証されるのは、 グローバル× グローバルスタティック○ ローカル○ ローカルスタティック○ という認識で良いのでしょうか? memsetについては、ややこしいので今まで避けてきたのですが、 一度よく勉強しておいた方がよさそうです。
- yaemon_2006
- ベストアンサー率22% (50/220)
>また、宣言時に初期化 () をする場合、0を100個書かなければなりません。 "int a[TMAX]={0};"でいい。
お礼
ありがとうございます。 最初の要素しか保証されないのではないでしょうか? "int a[TMAX]={-1};"などはうまくいきませんでした。
補足
No10さんの補足と併せて、ご回答の意味を理解できました。 ありがとうございました。
- tyatsumi
- ベストアンサー率58% (30/51)
指定範囲のメモリ領域を同じ値で埋め尽くすmemset()という 標準ライブラリ関数があります。 #include <string.h> しておいて、 main() の中で memset(a, 0, TMAX); などと書きます。
お礼
ありがとうございます。 memset便利ですね! memsetはintの0初期化以外だと、使えないような話を聞くので、使わないようにしてます。
- hidebun
- ベストアンサー率50% (92/181)
static変数はプログラム開始時に全要素0で初期化される。 だから、bとdは0が保証される。
お礼
staticならば保証されるのですね。初めて知りました。 ありがとうございます。
- 1
- 2
お礼
ご紹介いただいたサイトで、うやむやな理解がはっきりしました。 ありがとうございます。 Linux以外での開発を行ったことがないので、 Windows(またはその他)への移植性も意識して開発していきたいと思います。