OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
締切り
済み

C++ 2次元配列について 【 初心者です 】

  • すぐに回答を!
  • 質問No.222916
  • 閲覧数390
  • ありがとう数1
  • 気になる数0
  • 回答数5
  • コメント数0

お礼率 0% (0/5)

こんにちは.C++初心者です.
以下のプログラムは,
オブジェクトの2次元配列の作成と
そのアクセスをポインタで行うことを
目的としています.

以下の□■部が質問箇所です.
なぜobをsamp型でキャストするのか分かりません.
obはすでにsamp型で宣言しているのに…
それと※部において
2度目のp++処理について教えていただきたいです.
メモリーイメージを書いてもらえると
ありがたいです。
よろしくおねがいします。





#include <iostream.h>
using namespace std;

class samp {
int a;
public:
samp(int n) { a = n; }
int get_val() { return a; }
};


int main(void)
{
samp ob[3][2] = {
1, 2
3, 4,
5, 6
};
int i;

samp *p;

// □■□■□■□■
p = (samp *) ob;

for(i = 0; i < 3; i++) {
cout << p->get_val() << ' ';
p++;
※ cout << p->get_val() << endl;
※ p++;
}

cout << endl;

return 0;
}


}
通報する
  • 回答数5
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

回答 (全5件)

  • 回答No.1
レベル12

ベストアンサー率 48% (325/664)

>なぜobをsamp型でキャストするのか分かりません. >obはすでにsamp型で宣言しているのに… おしい。obはsamp**形の定数と考えたほうがいいです。 また、キャストされた型はsamp*形です。 C/C++では、ポインタ形と元の型とでは明確に異なります。 >それと※部において >2度目のp++処理について教えていただきたいです. >メモリーイメージを書いてもらえると ...続きを読む
>なぜobをsamp型でキャストするのか分かりません.
>obはすでにsamp型で宣言しているのに…
おしい。obはsamp**形の定数と考えたほうがいいです。
また、キャストされた型はsamp*形です。
C/C++では、ポインタ形と元の型とでは明確に異なります。

>それと※部において
>2度目のp++処理について教えていただきたいです.
>メモリーイメージを書いてもらえると
>ありがたいです。
配列obの各要素は、メモリ上では次のように並んでいます。
 ob[0][0],ob[0][1],ob[1][0],ob[1][1],ob[2][0],ob[2][1]
そして、obという値はob[0][0]を指すポインタ値となります。
このポインタ値の型は前述のとおりsamp**なのですが、これをsamp*型にキャストすることで上記の並びをあたかも1次配列であるかのように扱えるようになります。
最初のcout<<…ではob[i][0]の内容を出力し、p++することでメモリ上での次の要素であるob[i][1]をpが指すようにしてやっています。
2回目のcout<<…でob[i][1]の内容を出力し、p++することでメモリ上での次の要素であるob[i+1][0]をpが指すようにしてやっています。

…しかし、もし私がこのプログラムを監査する立場にあったら、この部分を添字を使って書くようにさせます(処理速度が問題になってるならば別ですが)。
なぜなら、このようなコードはのちのメンテナンスで処理を追いにくくする要因だからです。
補足コメント
soramamegorou

お礼率 0% (0/5)

さっそく詳細な解説ありがとうございます。
内容は大筋理解できました。
ところでメンテナンスで処理を追いにくくする要因とは、
具体的にはどのような影響があるのですか?
私は,学生のみで実際の開発現場はよく分かりませんので
ご教示いただけれるとこれから注意してコードを
書くことができるのですが。

ところで、添え字とすれば.。。。。

/*
ob[i * J_SIZE * j]
但し,J_SIZE は,#define J_SIZE ○ とマクロ定義されているものとします.
*/

といったコードでしょうか?

以上,よろしくおねがいします。
投稿日時 - 2002-02-22 18:47:39


  • 回答No.2
レベル12

ベストアンサー率 40% (201/496)

> p = (samp *) ob; 2次元配列の ob を単純に参照すると、型は samp** です。p = ob としてもコンパイル時にワーニングが出るだけでバイナリに違いはでません。 1回目のループで考えると、 >cout << p->get_val() << ' '; で p は ob[0][0]をさしています。 > ...続きを読む
> p = (samp *) ob;
2次元配列の ob を単純に参照すると、型は samp** です。p = ob としてもコンパイル時にワーニングが出るだけでバイナリに違いはでません。

1回目のループで考えると、
>cout << p->get_val() << ' ';
で p は ob[0][0]をさしています。
>p++;
p++することで ob[0][1] をさします
>※ cout << p->get_val() << endl;
p は ob[0][1]をさしています。
>※ p++;
で、ob[1][0] をさします

3回ループしたとき全ての ob配列は出力され、pはob配列の外側をさした状態で終了しますが、プログラム上で「使わないこと」を前提に問題有りません。

配列は連続したメモリイメージです。お絵かきをしてループを1ステップずつ追いかければ見えてくると思いますよ。
補足コメント
soramamegorou

お礼率 0% (0/5)

こんにちは。非常にわかりやすくかったです。
ポインタpの「後始末」というか
free(p)とメモリを解放せずにいました…
ありがとうございました。
投稿日時 - 2002-02-22 18:47:59
  • 回答No.3
レベル13

ベストアンサー率 24% (357/1463)

どう見ても初心者が勉強すべきコードじゃないな。 hitomuraさんのいう「添字を使って書く」ということですが、 p->getval() と書いてあるところを、 ob[i][0].get_val() という書き方にするということで良いと思います。 どうしてもポインタにこだわるのであれば、 そもそもobを二次元配列にする必然性のあるプログラムには見えないので、 samp ob[6] ...続きを読む
どう見ても初心者が勉強すべきコードじゃないな。

hitomuraさんのいう「添字を使って書く」ということですが、
p->getval()
と書いてあるところを、
ob[i][0].get_val()
という書き方にするということで良いと思います。
どうしてもポインタにこだわるのであれば、
そもそもobを二次元配列にする必然性のあるプログラムには見えないので、
samp ob[6];
という定義にしてしまえば、元々のご質問であるキャストも
不要になりますし、C++のコードとしては、その方がすっきりします。
samp (*p)[2];
という定義の仕方もありますが、これも初心者にはお勧めしません。
  • 回答No.4
レベル12

ベストアンサー率 40% (201/496)

>free(p)とメモリを解放せずにいました… これは、まずいですよ^^;)。freeで解放するのは mallocしたものです。同様に deleteしていいのは newした領域です。 このプログラム上では、p は ob配列の領域を指すアドレスを一時的に格納する為の変数です。 #1の方の補足部分ですが >ところでメンテナンスで処理を追いにくくする要因とは、 今回の場合、ポインタでル ...続きを読む
>free(p)とメモリを解放せずにいました…
これは、まずいですよ^^;)。freeで解放するのは mallocしたものです。同様に deleteしていいのは newした領域です。
このプログラム上では、p は ob配列の領域を指すアドレスを一時的に格納する為の変数です。

#1の方の補足部分ですが
>ところでメンテナンスで処理を追いにくくする要因とは、
今回の場合、ポインタでループする特別な理由がない限り普通に配列で参照した方があとで見直したときに解りやすいと思います。
for (i = 0; i < 3; i++) {
 cout << ob[i][0].get_val() << ' ';
 cout << ob[i][1].get_val() << endl;
}
もっと大きなプログラムですと顕著です。1ヶ月後の自分でも解るプログラムを書くようにしましょう>自分(T_T)
  • 回答No.5
レベル12

ベストアンサー率 48% (325/664)

>ところでメンテナンスで処理を追いにくくする要因とは、 >具体的にはどのような影響があるのですか? それは、あなたが1番理解しているはずです。 あなたは、このコードを見て、どうしてこういう処理で動くのか理解できずにこちらに質問されました。 プログラムのメンテナンスというのはプログラムを作った人間とは別の人間が行うことが多々あります。 メンテナンスとはようするにコードの修正なのですが、修正 ...続きを読む
>ところでメンテナンスで処理を追いにくくする要因とは、
>具体的にはどのような影響があるのですか?
それは、あなたが1番理解しているはずです。
あなたは、このコードを見て、どうしてこういう処理で動くのか理解できずにこちらに質問されました。

プログラムのメンテナンスというのはプログラムを作った人間とは別の人間が行うことが多々あります。
メンテナンスとはようするにコードの修正なのですが、修正するにはそのコードの動きを理解しなくてはなりません。
そのとき、このように理解しづらいコードがあると、その分メンテナンス作業が遅れることになります。
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ