配列初期化時の奇妙な値

私はC言語でのプログラミングに慣れていないと私は私が理解できないものを見つけました:

値を指定せずに配列を初期化すると、すべての要素がゼロになると思いました。私はこの数行のコードを書きました...

int main()                    
{     
    int obj[10][4];

    for (int a = 0; a < 10; a++)
    {
        print("%d\t%d\t%d\t%d\n", obj[a][0], obj[a][1], obj[a][2], obj[a][3]);
    }            
}

...そしてその出力にかなり混乱していました:

0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       7661
7960    2697    2260    7960
1551630361      -2130960380     146780176       -2130960380

一部の値がゼロで、一部の値がゼロではない理由がわかりません。私はもっ​​とコードを追加するとこの数字が変わることをもっと混乱しました。たとえば、前の例を変更して別の print()を追加しました...

int main()                    
{     
    int obj[10][4];

    print("start\tstop\tcenter\tdist\n\n");

    for (int a = 0; a < 10; a++)
    {
        print("%d\t%d\t%d\t%d\n", obj[a][0], obj[a][1], obj[a][2], obj[a][3]);
    }            
}

...これを取得:

start   stop    center  dist

0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       7673
7972    2709    2272    7972
1551630361      -2130960380     146780176       -2130960380

より大きな配列を使用すると、この数は最後に見つかるだけではありません。最初のいくつかの値は常にゼロですが、それから「何か」が起こります。

解決策が見つかりました>ここSOでmemset()を使用します。これは私にとってはうまくいきますが、...ここで何が起こっているのでしょうか。

C初心者が理解できる言葉を使って、誰かがこれを説明できますか?

2
初期化していないので、初期化されていない値になります。ほとんどゼロですが、保証されることはありません。
追加された 著者 stefan,
さらに発展させるためのヒント:本当に奇妙な値で予期しない動作をするなら、 valgrind を試してみてください。これは、バグがどこにあるかについてのヒントを与えるかもしれません(未初期化変数はvalgrindによってかなりよく検出されます)。
追加された 著者 stefan,
はい、私はこれが初めに非常に多くあることを知っています、私を信頼します、私は初心者を知っています;-)しかしそれは何を探すべきかを知ることは常に役に立ちます。 2つのステップ:コンパイラ呼び出しに -g を追加します(たぶん今は gcc -Wall -std = c99 my_file.c -o my_binary と入力するので、これは gcc -g -Wall -std = c99 my_file.c -o my_binary )。 2番目のステップ: ./my_binary のように実行する代わりに、 valgrind ./my_binary を実行します。以上です。 "...未初期化値..."がある場合は、そこにファイルと行がリストされているので、問題を調べることができます。質問のコードで試してみてください。
追加された 著者 stefan,
ああ、なるほど。そうですね、私の考えでは、これは学習を少し難しくします。
追加された 著者 stefan,
@stefan:この情報をありがとう - しかしそれは今ちょっと多すぎる。私は valgrind を見て、もう少し長くCを使用した後に理解できるかもしれないいくつかのサイトをブックマークしました;-)
追加された 著者 xph,
@stefan:えーと、それは…私は「いつもの」方法をコーディングしていないのです。私は小さなPropellerボードのためにCで書いて、まさしくその小さなコンピュータのために造られたIDEを使っています。私は通常のコンパイラさえも使っていません。それは、ボード上にコードを載せるのに最も便利な方法、つまり「完了したらこのボタンをクリックする」です。それに固執するつもりなら、私はそれをより深く見ていると思います。たぶん私は私の選択のツールを使ってこのコンピューターをプログラムすることができます、そしてこれはとても便利になるでしょう!
追加された 著者 xph,
はい、同意しました。 Cの「適切な」使用法を教えるつもりはありません - しかし、それは私にとって重要なことではありません。このボードはロボティクスを構築して学ぶように設計されており、私は主にセンサーやサーボなどに焦点を当てています。もちろん、物事を成し遂げるためにコードが必要です。少なくともC、これまで私がいつも避けてきた言語と「連絡をとる」ための理由。しかし、IDEは...本当によくありません。私は新しい冒険を探しているなら、私はそれを取り除こうとします。
追加された 著者 xph,

7 答え

Simply put, you can not assume the array is initialized to 0 unless you explicitly made the initialization yourself. The C standard does not guarantee anything about the content of the array, just that you'll have memory allocated for it.
A great reference on initializing and arrays in C general can be found here:http://www.tutorialspoint.com/cprogramming/c_multi_dimensional_arrays.htm

4
追加された
...だから私はそれを誤解しました。説明とリンクをありがとう!
追加された 著者 xph,

変数の宣言はありますが、初期化はありません。

もしあなたの配列をゼロで初期化したいのであれば、単にこれを入れてください:

int obj[10][4] = {0};
2
追加された
ありがとうございました!今、私は自分のミスを知っています - いくつかの 値が定義されている場合のみ、残りはゼロになります。それをします!
追加された 著者 xph,

int obj [10] [4] の格納クラス型は auto で、スタックに格納されています。 auto 変数は初期化された値を取得しません、すなわちそれらはゴミ値を持ちます。 。

1
追加された

初期値はすべて未定義です。あなたのコードは単に配列を定義します - それはその中にあるものに値を決して割り当てません。

1
追加された
@ xphはい、それはまさにあなたが間違っているところです。初期化されていないとは、ゴミの値です。
追加された 著者 stefan,
はい - でも、私が出くわした例は、「値なし」は「ゼロ、その後は」という意味です。私はそれが間違っていると思い、「値なし」は単に「何でも」を意味します。
追加された 著者 xph,
@ステファン:手に入れた! :-)
追加された 著者 xph,

プログラムがスタック上で定義された変数に特定の値を入れるまで、スタックはごみを含みます。 スタートアップコードはスタックの内容を初期化しません。

注:グローバルスペース/ファイルグローバルスペース内の変数は、スタートアップコードによって初期化されます。特定のイニシャライザが指定されていない場合、メモリは0x00に設定されます。

0
追加された

最初は、配列にガベージ値または予測不能な値があります。これらの値がどのようになるのか、または配列のどこに配置されるのかはわかりません。

Cで配列を宣言するたびに、使用する前に初期化してください。つまり、ループを実行してすべての配列位置をゼロまたは格納したい任意の数に初期化します。こうすれば、配列に何が含まれているのかを確実に知ることができます。さらに処理を進めても、配列に未定義の動作は表示されません。

0
追加された

専門家ではなく経験からの仮説:

配列を static int myArray [1000] として初期化すると、プログラムの実行中、Cは1000個のゼロで埋められた新しいメモリを割り当てます。 int myArray [1000] で初期化すると、1000個のレジスタが確保されます。その中には、以前のレジスタの使用時の古い値が含まれているものもあります。

0
追加された