ページ 11

別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月19日(火) 22:25
by まさき
よろしくお願いします。
同学年6クラスという構造体をつくり、
クラスごとに、いくつかのグループで成績を管理したいと思います。

Class[5]
------------------------
Group_A[4]
番号(int No;)
成績(int Score)
名前(char Name)
年齢(int age)

Group_B[3]
番号
成績(int Score)
名前(char Name)
体重(double wight)
-------------------------

上記のような、中の形状が異なる入れ子状の構造体を作成しました。
初期状態に0を代入してから、それぞれに値を入れています。
成績の部分を数回更新して、そのたび値の代入をしようとしているのですが、
問題が出てきて困っています。

Class[0].Group_B[0].Score = 80;と代入したところ、
Class[0].Group_B[1].Score などにも「80」が入っていました。
知人に相談したところ、宣言した成績の変数が全て「int Score」だから
格納されている場所に関係なく、代入された値は
すべての「int Score」に同じ値が入っているのではとのことでした。

それにしては、値「80」が入っていない構造体のあるので、
正直あまり納得できていません。


とりあえず、
int Score[4] と配列にして、

(構造体名).Group_B[1].Score[1] = 80;
(構造体名).Group_B[2].Score[2] このように
住み分けさせて、別に取り扱えるようにしよう考えています。

しかし知人の論法ですと、違うグループも同様になるのではと思います。
(構造体名).Group_B[1].Score[1] = 80;
(構造体名).Group_A[1].Score[1]にも、80が入ってしまうことになります。


この問題は、知人の言うとおり、代入された値はすべての「int Score」に
値が入るからなのでしょうか?
もし、そうでしたら、何か解決方法は無いでしょうか?
変数名を変えれば良いのですが、都合があって同じ変数名で統一したいのです。

ご存知の方がおりましたら教えてください。よろしくお願いいたします。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月19日(火) 22:33
by box
まさき さんが書きました: 知人に相談したところ、宣言した成績の変数が全て「int Score」だから
格納されている場所に関係なく、代入された値は
すべての「int Score」に同じ値が入っているのではとのことでした。
それは間違いです。

くだんの現象が起きているコードを見せていただけますでしょうか。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月19日(火) 22:55
by まさき
ご返事ありがとうございます。
コードが手元に無い(学校においてきた)ため、
簡易化した文で質問してしまいました。

明日の夜にはコードを載せたいと思います。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月20日(水) 20:53
by まさき
まさきです。
すみません。自己解決しました。

原因は不明ですが、
Group_A[4].NO への代入が、
Group_B[0].NOと干渉し合っていたようでした。

必要なのは数+1個用意して、
Group_A[5]として、[0]~[4]を使用するようにしたところ、
問題なくそれぞれに代入が可能になりました。

お騒がせしました。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月20日(水) 21:27
by softya(ソフト屋)
配列の要素数超えてると操作している配列に関係ない変数領域にアクセスします。
Group_A[4].NOの指す所がたまたまGroup_B[0].NOの場所だったのでしょう。
これはC言語で非常に多いバグですから気をつけて下さい。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月20日(水) 21:36
by box
まさき さんが書きました: 必要なのは数+1個用意して、
Group_A[5]として、[0]~[4]を使用するようにしたところ、
解決策としてはちょっとナニですね。
必要な数の分、ちょうどだけ用意すれば何も問題ないはずです。コードにバグがなければ。

a[4]と定義した配列にアクセスするときにa[4]と書いた、ってことでしょうか。これはダメですよ。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月21日(木) 01:36
by まさき
まさきです。
色々なご意見ありがとうございます。

>配列の要素数超えてると操作している配列に関係ない変数領域にアクセスします。
>Group_A[4].NOの指す所がたまたまGroup_B[0].NOの場所だったのでしょう。
>これはC言語で非常に多いバグですから気をつけて下さい。

>解決策としてはちょっとナニですね。
>必要な数の分、ちょうどだけ用意すれば何も問題ないはずです。コードにバグがなければ。

なるほど。これがバグの原因でしたか……
5個の値を入れたいので、[0]~[4]としていた。しかし、これが要素数を超えていると判断されている。
このことは、[4]に値を入れたときの、他の場所の挙動よりバグがあるとわかる。

実際配列を[5]として作成し、[4]までに値を入れると、その領域にのみ格納されて、バグは発生しない。
ピッタリだと思っていたのですが、ドコかしらに問題があるのでしょうか……


>a[4]と定義した配列にアクセスするときにa[4]と書いた、ってことでしょうか。これはダメですよ。
あれ? これはどうしていけないのですか?
勉強不足で申し訳ありません。教えていただけ無いでしょうか。お願いします。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月21日(木) 03:09
by MoNoQLoREATOR
例えば

int a[4];

と宣言したら要素は4つです。
取り出すときはこう↓

a[0]; //0番目の要素を取り出す
a[1]; //1番目の要素を取り出す
a[2]; //2番目の要素を取り出す
a[3]; //3番目の要素を取り出す
a[4]; //4番目の要素を取り出す

あれ?要素数が5個に増えてませんか?
この場合

a[4];

はどこかわけのわからない場所にアクセスしちゃってるわけですよ。
だからダメなんです。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月21日(木) 05:59
by box
まさき さんが書きました: >a[4]と定義した配列にアクセスするときにa[4]と書いた、ってことでしょうか。これはダメですよ。
あれ? これはどうしていけないのですか?
int a[4];
と定義したとき、確保できているのは4つ分の領域です。
それは、a[0]~a[3]の4つです。4つ分の領域、というのが、
int a[4];
の「4」の意味です。
よって、この配列にアクセスする際、例えば
a[4]=12345;
などと書いてしまうと、配列の定義範囲外の領域にアクセスしており、
何かわけのわからないエラー(例えば今回のような)の原因となりかねません。

Re: 別々の構造体内部に同変数を使用した場合の住み分け

Posted: 2012年6月21日(木) 23:39
by まさき
まさきです。
解決済みのスレッドを無意味に上げるのも失礼なので、
このレスを最後にしたいと思います。

>int a[4];
>と定義したとき、確保できているのは4つ分の領域です。
>それは、a[0]~a[3]の4つです。4つ分の領域、というのが、
>int a[4];
>の「4」の意味です。

なるほど。
どうも私は、5個の要素を欲しい場合 int a[4]とすれば
[0]~[4]の領域ができるとカン違いしていたようです。
実際には[0]~[3]の4要素なわけですから、当然[4]を指定すればバグが出ますね。
大変勉強になりました。

box様、 softya(ソフト屋)様、 MoNoQLoREATOR様、
勉強不足な初心者の質問に、丁寧なご指導、誠にありがとうございました。