こんにちは.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;
}
}
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
>なぜ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が指すようにしてやっています。
…しかし、もし私がこのプログラムを監査する立場にあったら、この部分を添字を使って書くようにさせます(処理速度が問題になってるならば別ですが)。
なぜなら、このようなコードはのちのメンテナンスで処理を追いにくくする要因だからです。
この回答への補足
さっそく詳細な解説ありがとうございます。
内容は大筋理解できました。
ところでメンテナンスで処理を追いにくくする要因とは、
具体的にはどのような影響があるのですか?
私は,学生のみで実際の開発現場はよく分かりませんので
ご教示いただけれるとこれから注意してコードを
書くことができるのですが。
ところで、添え字とすれば.。。。。
/*
ob[i * J_SIZE * j]
但し,J_SIZE は,#define J_SIZE ○ とマクロ定義されているものとします.
*/
といったコードでしょうか?
以上,よろしくおねがいします。
No.2
- 回答日時:
> 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ステップずつ追いかければ見えてくると思いますよ。
この回答への補足
こんにちは。非常にわかりやすくかったです。
ポインタpの「後始末」というか
free(p)とメモリを解放せずにいました…
ありがとうございました。
No.3
- 回答日時:
どう見ても初心者が勉強すべきコードじゃないな。
hitomuraさんのいう「添字を使って書く」ということですが、
p->getval()
と書いてあるところを、
ob[i][0].get_val()
という書き方にするということで良いと思います。
どうしてもポインタにこだわるのであれば、
そもそもobを二次元配列にする必然性のあるプログラムには見えないので、
samp ob[6];
という定義にしてしまえば、元々のご質問であるキャストも
不要になりますし、C++のコードとしては、その方がすっきりします。
samp (*p)[2];
という定義の仕方もありますが、これも初心者にはお勧めしません。
No.4
- 回答日時:
>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
- 回答日時:
>ところでメンテナンスで処理を追いにくくする要因とは、
>具体的にはどのような影響があるのですか?
それは、あなたが1番理解しているはずです。
あなたは、このコードを見て、どうしてこういう処理で動くのか理解できずにこちらに質問されました。
プログラムのメンテナンスというのはプログラムを作った人間とは別の人間が行うことが多々あります。
メンテナンスとはようするにコードの修正なのですが、修正するにはそのコードの動きを理解しなくてはなりません。
そのとき、このように理解しづらいコードがあると、その分メンテナンス作業が遅れることになります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C++のcinの動作 5 2023/02/26 00:13
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# C++初心者です stirng 2 2022/09/20 20:43
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- C言語・C++・C# 至急教えてください! プログラミングの問題です! お願いします! 出力2と全く同じ出力をするように、 2 2022/06/22 23:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列を使わずに、変数名を動的...
-
C言語 配列の長さの上限
-
C言語初心者 構造体 課題について
-
複数の選択範囲の行番号を個別...
-
C言語初心者 ポインタについて...
-
unsigned char配列への入力の仕方
-
入力関数(配列4個)を作成するプ...
-
配列で格納したものをmsgboxで...
-
ExcelVBAで質問です。離れた二...
-
配列の参照渡しで型が一致しま...
-
配列をEraseしてもメモリが開放...
-
C言語で特定列だけを抽出して配...
-
VBで動的なメモリの確保
-
スマホの数字キーをISOの配置に...
-
【速いブラインドタッチ】手を...
-
char型の配列 char buff[20] = ...
-
int型をchar型に(右詰で)代入...
-
パイソンの
-
先頭アドレスとは何ですか?
-
c++によるジャンケンプログラム
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列の参照渡しで型が一致しま...
-
配列を使わずに、変数名を動的...
-
VBで構造体の配列を関数に渡す...
-
配列で格納したものをmsgboxで...
-
unsigned char配列への入力の仕方
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
擬似コード 長さがmの配列でな...
-
【速いブラインドタッチ】手を...
-
パイソンの
-
C言語初心者 ポインタについて...
-
ExcelVBAで質問です。離れた二...
-
配列を含む構造体の初期値について
-
複数の選択範囲の行番号を個別...
-
Functionの戻り値を2次元配列...
-
C++ vectorに配列をプッシュしたい
-
先頭アドレスとは何ですか?
-
テキストファイルから文字列を...
-
Redimした動的配列はEraseする...
おすすめ情報